Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
mycard
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
syntax_j
mycard
Commits
da3a1104
Commit
da3a1104
authored
Dec 06, 2016
by
wudizhanche1000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
合并InstallService和AppService
parent
0759508b
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
315 additions
and
330 deletions
+315
-330
app/app-detail.component.ts
app/app-detail.component.ts
+8
-6
app/apps.service.ts
app/apps.service.ts
+306
-4
app/install.service.ts
app/install.service.ts
+0
-315
app/lobby.component.ts
app/lobby.component.ts
+1
-3
app/mycard.module.ts
app/mycard.module.ts
+0
-2
No files found.
app/app-detail.component.ts
View file @
da3a1104
...
@@ -7,7 +7,6 @@ import {DownloadService} from "./download.service";
...
@@ -7,7 +7,6 @@ import {DownloadService} from "./download.service";
import
{
clipboard
,
remote
}
from
"
electron
"
;
import
{
clipboard
,
remote
}
from
"
electron
"
;
import
*
as
path
from
"
path
"
;
import
*
as
path
from
"
path
"
;
import
*
as
fs
from
'
fs
'
;
import
*
as
fs
from
'
fs
'
;
import
{
InstallService
}
from
"
./install.service
"
;
import
mkdirp
=
require
(
"
mkdirp
"
);
import
mkdirp
=
require
(
"
mkdirp
"
);
declare
const
Notification
:
any
;
declare
const
Notification
:
any
;
...
@@ -30,8 +29,7 @@ export class AppDetailComponent implements OnInit {
...
@@ -30,8 +29,7 @@ export class AppDetailComponent implements OnInit {
referencesInstall
:
{[
id
:
string
]:
boolean
};
referencesInstall
:
{[
id
:
string
]:
boolean
};
constructor
(
private
appsService
:
AppsService
,
private
settingsService
:
SettingsService
,
constructor
(
private
appsService
:
AppsService
,
private
settingsService
:
SettingsService
,
private
downloadService
:
DownloadService
,
private
installService
:
InstallService
,
private
downloadService
:
DownloadService
,
private
ref
:
ChangeDetectorRef
)
{
private
ref
:
ChangeDetectorRef
)
{
}
}
// public File[] listRoots() {
// public File[] listRoots() {
...
@@ -103,8 +101,12 @@ export class AppDetailComponent implements OnInit {
...
@@ -103,8 +101,12 @@ export class AppDetailComponent implements OnInit {
async
uninstall
(
app
:
App
)
{
async
uninstall
(
app
:
App
)
{
if
(
confirm
(
"
确认删除?
"
))
{
if
(
confirm
(
"
确认删除?
"
))
{
await
this
.
installService
.
uninstall
(
app
);
try
{
app
.
status
.
status
=
"
init
"
;
await
this
.
appsService
.
uninstall
(
app
);
app
.
status
.
status
=
"
init
"
;
}
catch
(
e
)
{
alert
(
e
);
}
}
}
}
}
...
@@ -131,7 +133,7 @@ export class AppDetailComponent implements OnInit {
...
@@ -131,7 +133,7 @@ export class AppDetailComponent implements OnInit {
let
volume
=
this
.
installOption
.
installLibrary
.
slice
(
7
);
let
volume
=
this
.
installOption
.
installLibrary
.
slice
(
7
);
let
library
=
path
.
join
(
volume
,
"
MyCardLibrary
"
);
let
library
=
path
.
join
(
volume
,
"
MyCardLibrary
"
);
try
{
try
{
await
this
.
install
Service
.
createDirectory
(
library
);
await
this
.
apps
Service
.
createDirectory
(
library
);
this
.
installOption
.
installLibrary
=
library
;
this
.
installOption
.
installLibrary
=
library
;
this
.
settingsService
.
addLibrary
(
library
,
true
);
this
.
settingsService
.
addLibrary
(
library
,
true
);
}
catch
(
e
)
{
}
catch
(
e
)
{
...
...
app/apps.service.ts
View file @
da3a1104
import
{
Injectable
,
ApplicationRef
}
from
"
@angular/core
"
;
import
{
Injectable
,
ApplicationRef
,
EventEmitter
}
from
"
@angular/core
"
;
import
{
Http
}
from
"
@angular/http
"
;
import
{
Http
}
from
"
@angular/http
"
;
import
{
App
,
AppStatus
,
Action
}
from
"
./app
"
;
import
{
App
,
AppStatus
,
Action
}
from
"
./app
"
;
import
{
SettingsService
}
from
"
./settings.sevices
"
;
import
{
SettingsService
}
from
"
./settings.sevices
"
;
...
@@ -8,17 +8,30 @@ import * as child_process from "child_process";
...
@@ -8,17 +8,30 @@ import * as child_process from "child_process";
import
{
ChildProcess
}
from
"
child_process
"
;
import
{
ChildProcess
}
from
"
child_process
"
;
import
{
remote
}
from
"
electron
"
;
import
{
remote
}
from
"
electron
"
;
import
"
rxjs/Rx
"
;
import
"
rxjs/Rx
"
;
import
*
as
readline
from
"
readline
"
;
import
{
AppLocal
}
from
"
./app-local
"
;
import
{
AppLocal
}
from
"
./app-local
"
;
import
*
as
ini
from
"
ini
"
;
import
*
as
ini
from
"
ini
"
;
import
Timer
=
NodeJS
.
Timer
;
import
Timer
=
NodeJS
.
Timer
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
InstallOption
}
from
"
./install-option
"
;
import
{
InstallOption
}
from
"
./install-option
"
;
import
{
InstallService
}
from
"
./install.service
"
;
import
{
ComparableSet
}
from
"
./shared/ComparableSet
"
;
import
{
ComparableSet
}
from
"
./shared/ComparableSet
"
;
import
mkdirp
=
require
(
"
mkdirp
"
);
import
{
Observable
,
Observer
}
from
"
rxjs/Rx
"
;
import
ReadableStream
=
NodeJS
.
ReadableStream
;
const
Aria2
=
require
(
'
aria2
'
);
const
Aria2
=
require
(
'
aria2
'
);
const
sudo
=
require
(
'
electron-sudo
'
);
const
sudo
=
require
(
'
electron-sudo
'
);
interface
InstallTask
{
app
:
App
;
option
:
InstallOption
;
}
interface
InstallStatus
{
status
:
string
;
progress
:
number
;
total
:
number
;
lastItem
:
string
;
}
interface
Connection
{
interface
Connection
{
connection
:
WebSocket
,
address
:
string
|
null
connection
:
WebSocket
,
address
:
string
|
null
}
}
...
@@ -29,7 +42,17 @@ export class AppsService {
...
@@ -29,7 +42,17 @@ export class AppsService {
private
apps
:
Map
<
string
,
App
>
;
private
apps
:
Map
<
string
,
App
>
;
constructor
(
private
http
:
Http
,
private
settingsService
:
SettingsService
,
private
ref
:
ApplicationRef
,
constructor
(
private
http
:
Http
,
private
settingsService
:
SettingsService
,
private
ref
:
ApplicationRef
,
private
downloadService
:
DownloadService
,
private
installService
:
InstallService
)
{
private
downloadService
:
DownloadService
)
{
if
(
process
.
platform
===
"
win32
"
)
{
if
(
process
.
env
[
'
NODE_ENV
'
]
==
'
production
'
)
{
this
.
tarPath
=
path
.
join
(
process
.
resourcesPath
,
'
bin
'
,
'
bsdtar.exe
'
);
}
else
{
this
.
tarPath
=
path
.
join
(
'
bin
'
,
'
bsdtar.exe
'
);
}
}
else
{
this
.
tarPath
=
"
bsdtar
"
}
}
}
loadApps
()
{
loadApps
()
{
...
@@ -234,7 +257,7 @@ export class AppsService {
...
@@ -234,7 +257,7 @@ export class AppsService {
let
o
=
new
InstallOption
(
result
.
app
,
option
.
installLibrary
);
let
o
=
new
InstallOption
(
result
.
app
,
option
.
installLibrary
);
o
.
downloadFiles
=
result
.
files
;
o
.
downloadFiles
=
result
.
files
;
let
task
=
this
.
installService
.
push
({
app
:
result
.
app
,
option
:
o
});
let
task
=
this
.
push
({
app
:
result
.
app
,
option
:
o
});
installTasks
.
push
(
task
);
installTasks
.
push
(
task
);
}
}
await
Promise
.
all
(
installTasks
);
await
Promise
.
all
(
installTasks
);
...
@@ -439,4 +462,283 @@ export class AppsService {
...
@@ -439,4 +462,283 @@ export class AppsService {
this
.
ref
.
tick
();
this
.
ref
.
tick
();
};
};
}
}
tarPath
:
string
;
installingId
:
string
=
''
;
eventEmitter
=
new
EventEmitter
<
void
>
();
readonly
checksumURL
=
"
https://thief.mycard.moe/checksums/
"
;
readonly
updateServerURL
=
'
https://thief.mycard.moe/update/metalinks
'
;
installQueue
:
Map
<
string
,
InstallTask
>
=
new
Map
();
map
:
Map
<
string
,
string
>
=
new
Map
();
private
createId
():
string
{
function
s4
()
{
return
Math
.
floor
((
1
+
Math
.
random
())
*
0x10000
)
.
toString
(
16
)
.
substring
(
1
);
}
return
s4
()
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
s4
()
+
s4
();
}
// installProgress(id: string): Observable<InstallStatus>|undefined {
// let app = this.map.get(id);
// if (app) {
//
// }
// }
async
push
(
task
:
InstallTask
):
Promise
<
void
>
{
if
(
!
task
.
app
.
readyForInstall
())
{
await
new
Promise
((
resolve
,
reject
)
=>
{
this
.
eventEmitter
.
subscribe
(()
=>
{
if
(
task
.
app
.
readyForInstall
())
{
resolve
();
}
else
if
(
task
.
app
.
findDependencies
().
find
((
dependency
:
App
)
=>
!
dependency
.
isInstalled
()))
{
reject
(
"
Dependencies failed
"
);
}
});
});
}
await
this
.
doInstall
(
task
);
}
async
doInstall
(
task
:
InstallTask
)
{
try
{
let
app
=
task
.
app
;
let
dependencies
=
app
.
findDependencies
();
let
readyForInstall
=
dependencies
.
every
((
dependency
)
=>
{
return
dependency
.
isReady
();
});
if
(
readyForInstall
)
{
let
option
=
task
.
option
;
let
installDir
=
option
.
installDir
;
// if (!app.isInstalled()) {
let
checksumFile
=
await
this
.
getChecksumFile
(
app
);
if
(
app
.
parent
)
{
// mod需要安装到parent路径
installDir
=
app
.
parent
.
local
!
.
path
;
let
parentFiles
=
new
ComparableSet
(
Array
.
from
(
app
.
parent
.
local
!
.
files
.
keys
()));
let
appFiles
=
new
ComparableSet
(
Array
.
from
(
checksumFile
.
keys
()));
let
conflictFiles
=
appFiles
.
intersection
(
parentFiles
);
if
(
conflictFiles
.
size
>
0
)
{
let
backupPath
=
path
.
join
(
option
.
installLibrary
,
"
backup
"
,
app
.
parent
.
id
);
await
this
.
backupFiles
(
app
.
parent
.
local
!
.
path
,
backupPath
,
conflictFiles
);
}
}
let
allFiles
=
new
Set
(
checksumFile
.
keys
());
app
.
status
.
status
=
"
installing
"
;
app
.
status
.
total
=
allFiles
.
size
;
app
.
status
.
progress
=
0
;
// let timeNow = new Date().getTime();
for
(
let
file
of
option
.
downloadFiles
)
{
await
this
.
createDirectory
(
installDir
);
let
interval
=
setInterval
(()
=>
{
},
500
);
await
new
Promise
((
resolve
,
reject
)
=>
{
this
.
extract
(
file
,
installDir
).
subscribe
(
(
lastItem
:
string
)
=>
{
app
.
status
.
progress
+=
1
;
app
.
status
.
progressMessage
=
lastItem
;
},
(
error
)
=>
{
reject
(
error
);
},
()
=>
{
resolve
();
});
});
clearInterval
(
interval
);
}
await
this
.
postInstall
(
app
,
installDir
);
console
.
log
(
"
post install success
"
);
let
local
=
new
AppLocal
();
local
.
path
=
installDir
;
local
.
files
=
checksumFile
;
local
.
version
=
app
.
version
;
app
.
local
=
local
;
this
.
saveAppLocal
(
app
);
app
.
status
.
status
=
"
ready
"
;
}
// }
}
catch
(
e
)
{
console
.
log
(
"
exception in doInstall
"
,
e
);
throw
e
;
}
finally
{
this
.
eventEmitter
.
emit
();
}
}
createDirectory
(
dir
:
string
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
mkdirp
(
dir
,
resolve
);
})
}
extract
(
file
:
string
,
dir
:
string
):
Observable
<
string
>
{
return
Observable
.
create
((
observer
:
Observer
<
string
>
)
=>
{
let
tarProcess
=
child_process
.
spawn
(
this
.
tarPath
,
[
'
xvf
'
,
file
,
'
-C
'
,
dir
]);
let
rl
=
readline
.
createInterface
({
input
:
<
ReadableStream
>
tarProcess
.
stderr
,
});
rl
.
on
(
'
line
'
,
(
input
:
string
)
=>
{
observer
.
next
(
input
.
split
(
"
"
,
2
)[
1
]);
});
tarProcess
.
on
(
'
exit
'
,
(
code
)
=>
{
if
(
code
===
0
)
{
observer
.
complete
();
}
else
{
observer
.
error
(
code
);
}
});
return
()
=>
{
}
})
}
async
postInstall
(
app
:
App
,
appPath
:
string
)
{
let
action
=
app
.
actions
.
get
(
'
install
'
);
if
(
action
)
{
let
env
=
Object
.
assign
({},
action
.
env
);
let
command
:
string
[]
=
[];
command
.
push
(
path
.
join
(
appPath
,
action
.
execute
));
command
.
push
(...
action
.
args
);
let
open
=
action
.
open
;
if
(
open
)
{
let
openAction
:
any
=
open
.
actions
.
get
(
"
main
"
);
env
=
Object
.
assign
(
env
,
openAction
.
env
);
command
.
unshift
(...
openAction
.
args
);
command
.
unshift
(
path
.
join
((
<
AppLocal
>
open
.
local
).
path
,
openAction
.
execute
));
}
return
new
Promise
((
resolve
,
reject
)
=>
{
let
child
=
child_process
.
spawn
(
<
string
>
command
.
shift
(),
command
,
{
env
:
env
,
stdio
:
'
inherit
'
,
shell
:
true
,
});
child
.
on
(
'
error
'
,
(
error
)
=>
{
reject
(
error
);
});
child
.
on
(
'
exit
'
,
(
code
)
=>
{
if
(
code
===
0
)
{
resolve
(
code
);
}
else
{
reject
(
code
);
}
})
})
}
}
saveAppLocal
(
app
:
App
)
{
if
(
app
.
local
)
{
localStorage
.
setItem
(
app
.
id
,
JSON
.
stringify
(
app
.
local
));
}
}
async
backupFiles
(
dir
:
string
,
backupDir
:
string
,
files
:
Iterable
<
string
>
)
{
for
(
let
file
of
files
)
{
await
new
Promise
(
async
(
resolve
,
reject
)
=>
{
let
srcPath
=
path
.
join
(
dir
,
file
);
let
backupPath
=
path
.
join
(
backupDir
,
file
);
await
this
.
createDirectory
(
path
.
dirname
(
backupPath
));
fs
.
unlink
(
backupPath
,
(
err
)
=>
{
fs
.
rename
(
srcPath
,
backupPath
,
resolve
);
});
});
}
}
async
restoreFiles
(
dir
:
string
,
backupDir
:
string
,
files
:
Iterable
<
string
>
)
{
for
(
let
file
of
files
)
{
await
new
Promise
((
resolve
,
reject
)
=>
{
let
backupPath
=
path
.
join
(
backupDir
,
file
);
let
srcPath
=
path
.
join
(
dir
,
file
);
fs
.
unlink
(
srcPath
,
(
err
)
=>
{
fs
.
rename
(
backupPath
,
srcPath
,
resolve
);
})
})
}
}
async
getChecksumFile
(
app
:
App
):
Promise
<
Map
<
string
,
string
>
>
{
let
checksumUrl
=
this
.
checksumURL
+
app
.
id
;
if
([
"
ygopro
"
,
'
desmume
'
].
includes
(
app
.
id
))
{
checksumUrl
=
this
.
checksumURL
+
app
.
id
+
"
-
"
+
process
.
platform
;
}
return
this
.
http
.
get
(
checksumUrl
)
.
map
((
response
)
=>
{
let
map
=
new
Map
<
string
,
string
>
();
for
(
let
line
of
response
.
text
().
split
(
'
\n
'
))
{
if
(
line
!==
""
)
{
let
[
checksum
,
filename
]
=
line
.
split
(
'
'
,
2
);
if
(
filename
.
endsWith
(
"
\\
"
)
||
filename
.
endsWith
(
"
/
"
))
{
map
.
set
(
filename
,
""
);
}
map
.
set
(
filename
,
checksum
);
}
}
return
map
;
}).
toPromise
();
}
deleteFile
(
file
:
string
):
Promise
<
string
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
fs
.
lstat
(
file
,
(
err
,
stats
)
=>
{
if
(
err
)
return
resolve
(
path
);
if
(
stats
.
isDirectory
())
{
fs
.
rmdir
(
file
,
(
err
)
=>
{
resolve
(
file
);
});
}
else
{
fs
.
unlink
(
file
,
(
err
)
=>
{
resolve
(
file
);
});
}
});
})
}
async
uninstall
(
app
:
App
)
{
let
children
=
this
.
findChildren
(
app
);
let
hasInstalledChild
=
children
.
find
((
child
)
=>
{
return
child
.
isInstalled
();
});
if
(
hasInstalledChild
)
{
throw
"
无法卸载,还有依赖此程序的游戏。
"
}
if
(
app
.
isReady
())
{
app
.
status
.
status
=
"
uninstalling
"
;
let
appDir
=
app
.
local
!
.
path
;
let
files
=
Array
.
from
(
app
.
local
!
.
files
.
keys
()).
sort
().
reverse
();
app
.
status
.
total
=
files
.
length
;
for
(
let
file
of
files
)
{
app
.
status
.
progress
+=
1
;
await
this
.
deleteFile
(
path
.
join
(
appDir
,
file
));
}
if
(
app
.
parent
)
{
let
backupDir
=
path
.
join
(
path
.
dirname
(
appDir
),
"
backup
"
,
app
.
parent
.
id
)
let
fileSet
=
new
ComparableSet
(
files
);
let
parentSet
=
new
ComparableSet
(
Array
.
from
(
app
.
parent
.
local
!
.
files
.
keys
()));
let
difference
=
parentSet
.
intersection
(
fileSet
);
if
(
difference
)
{
this
.
restoreFiles
(
appDir
,
backupDir
,
Array
.
from
(
difference
))
}
}
app
.
local
=
null
;
localStorage
.
removeItem
(
app
.
id
);
}
}
}
}
\ No newline at end of file
app/install.service.ts
deleted
100644 → 0
View file @
0759508b
/**
* Created by weijian on 2016/11/2.
*/
import
{
Injectable
,
ApplicationRef
,
EventEmitter
}
from
"
@angular/core
"
;
import
{
App
,
Category
}
from
"
./app
"
;
import
{
InstallOption
}
from
"
./install-option
"
;
import
*
as
path
from
"
path
"
;
import
*
as
child_process
from
"
child_process
"
;
import
*
as
mkdirp
from
"
mkdirp
"
;
import
*
as
readline
from
"
readline
"
;
import
*
as
fs
from
"
fs
"
;
import
{
AppLocal
}
from
"
./app-local
"
;
import
{
Http
}
from
"
@angular/http
"
;
import
{
ComparableSet
}
from
"
./shared/ComparableSet
"
import
ReadableStream
=
NodeJS
.
ReadableStream
;
import
{
Observable
,
Observer
}
from
"
rxjs/Rx
"
;
export
interface
InstallTask
{
app
:
App
;
option
:
InstallOption
;
}
export
interface
InstallStatus
{
status
:
string
;
progress
:
number
;
total
:
number
;
lastItem
:
string
;
}
@
Injectable
()
export
class
InstallService
{
tarPath
:
string
;
installingId
:
string
=
''
;
eventEmitter
=
new
EventEmitter
<
void
>
();
readonly
checksumURL
=
"
https://thief.mycard.moe/checksums/
"
;
readonly
updateServerURL
=
'
https://thief.mycard.moe/update/metalinks
'
;
installQueue
:
Map
<
string
,
InstallTask
>
=
new
Map
();
map
:
Map
<
string
,
string
>
=
new
Map
();
constructor
(
private
http
:
Http
,
private
ref
:
ApplicationRef
)
{
if
(
process
.
platform
===
"
win32
"
)
{
if
(
process
.
env
[
'
NODE_ENV
'
]
==
'
production
'
)
{
this
.
tarPath
=
path
.
join
(
process
.
resourcesPath
,
'
bin
'
,
'
bsdtar.exe
'
);
}
else
{
this
.
tarPath
=
path
.
join
(
'
bin
'
,
'
bsdtar.exe
'
);
}
}
else
{
this
.
tarPath
=
"
bsdtar
"
}
}
private
createId
():
string
{
function
s4
()
{
return
Math
.
floor
((
1
+
Math
.
random
())
*
0x10000
)
.
toString
(
16
)
.
substring
(
1
);
}
return
s4
()
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
'
-
'
+
s4
()
+
s4
()
+
s4
();
}
// installProgress(id: string): Observable<InstallStatus>|undefined {
// let app = this.map.get(id);
// if (app) {
//
// }
// }
async
push
(
task
:
InstallTask
):
Promise
<
void
>
{
if
(
!
task
.
app
.
readyForInstall
())
{
await
new
Promise
((
resolve
,
reject
)
=>
{
this
.
eventEmitter
.
subscribe
(()
=>
{
if
(
task
.
app
.
readyForInstall
())
{
resolve
();
}
else
if
(
task
.
app
.
findDependencies
().
find
((
dependency
:
App
)
=>
!
dependency
.
isInstalled
()))
{
reject
(
"
Dependencies failed
"
);
}
});
});
}
await
this
.
doInstall
(
task
);
}
async
doInstall
(
task
:
InstallTask
)
{
try
{
let
app
=
task
.
app
;
let
dependencies
=
app
.
findDependencies
();
let
readyForInstall
=
dependencies
.
every
((
dependency
)
=>
{
return
dependency
.
isReady
();
});
if
(
readyForInstall
)
{
let
option
=
task
.
option
;
let
installDir
=
option
.
installDir
;
// if (!app.isInstalled()) {
let
checksumFile
=
await
this
.
getChecksumFile
(
app
);
if
(
app
.
parent
)
{
// mod需要安装到parent路径
installDir
=
app
.
parent
.
local
!
.
path
;
let
parentFiles
=
new
ComparableSet
(
Array
.
from
(
app
.
parent
.
local
!
.
files
.
keys
()));
let
appFiles
=
new
ComparableSet
(
Array
.
from
(
checksumFile
.
keys
()));
let
conflictFiles
=
appFiles
.
intersection
(
parentFiles
);
if
(
conflictFiles
.
size
>
0
)
{
let
backupPath
=
path
.
join
(
option
.
installLibrary
,
"
backup
"
,
app
.
parent
.
id
);
await
this
.
backupFiles
(
app
.
parent
.
local
!
.
path
,
backupPath
,
conflictFiles
);
}
}
let
allFiles
=
new
Set
(
checksumFile
.
keys
());
app
.
status
.
status
=
"
installing
"
;
app
.
status
.
total
=
allFiles
.
size
;
app
.
status
.
progress
=
0
;
// let timeNow = new Date().getTime();
for
(
let
file
of
option
.
downloadFiles
)
{
await
this
.
createDirectory
(
installDir
);
let
interval
=
setInterval
(()
=>
{
},
500
);
await
new
Promise
((
resolve
,
reject
)
=>
{
this
.
extract
(
file
,
installDir
).
subscribe
(
(
lastItem
:
string
)
=>
{
app
.
status
.
progress
+=
1
;
app
.
status
.
progressMessage
=
lastItem
;
},
(
error
)
=>
{
reject
(
error
);
},
()
=>
{
resolve
();
});
});
clearInterval
(
interval
);
}
await
this
.
postInstall
(
app
,
installDir
);
console
.
log
(
"
post install success
"
);
let
local
=
new
AppLocal
();
local
.
path
=
installDir
;
local
.
files
=
checksumFile
;
local
.
version
=
app
.
version
;
app
.
local
=
local
;
this
.
saveAppLocal
(
app
);
app
.
status
.
status
=
"
ready
"
;
}
// }
}
catch
(
e
)
{
console
.
log
(
"
exception in doInstall
"
,
e
);
throw
e
;
}
finally
{
this
.
eventEmitter
.
emit
();
}
}
createDirectory
(
dir
:
string
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
mkdirp
(
dir
,
resolve
);
})
}
extract
(
file
:
string
,
dir
:
string
):
Observable
<
string
>
{
return
Observable
.
create
((
observer
:
Observer
<
string
>
)
=>
{
let
tarProcess
=
child_process
.
spawn
(
this
.
tarPath
,
[
'
xvf
'
,
file
,
'
-C
'
,
dir
]);
let
rl
=
readline
.
createInterface
({
input
:
<
ReadableStream
>
tarProcess
.
stderr
,
});
rl
.
on
(
'
line
'
,
(
input
:
string
)
=>
{
observer
.
next
(
input
.
split
(
"
"
,
2
)[
1
]);
});
tarProcess
.
on
(
'
exit
'
,
(
code
)
=>
{
if
(
code
===
0
)
{
observer
.
complete
();
}
else
{
observer
.
error
(
code
);
}
});
return
()
=>
{
}
})
}
async
postInstall
(
app
:
App
,
appPath
:
string
)
{
let
action
=
app
.
actions
.
get
(
'
install
'
);
if
(
action
)
{
let
env
=
Object
.
assign
({},
action
.
env
);
let
command
:
string
[]
=
[];
command
.
push
(
path
.
join
(
appPath
,
action
.
execute
));
command
.
push
(...
action
.
args
);
let
open
=
action
.
open
;
if
(
open
)
{
let
openAction
:
any
=
open
.
actions
.
get
(
"
main
"
);
env
=
Object
.
assign
(
env
,
openAction
.
env
);
command
.
unshift
(...
openAction
.
args
);
command
.
unshift
(
path
.
join
((
<
AppLocal
>
open
.
local
).
path
,
openAction
.
execute
));
}
return
new
Promise
((
resolve
,
reject
)
=>
{
let
child
=
child_process
.
spawn
(
<
string
>
command
.
shift
(),
command
,
{
env
:
env
,
stdio
:
'
inherit
'
,
shell
:
true
,
});
child
.
on
(
'
error
'
,
(
error
)
=>
{
reject
(
error
);
});
child
.
on
(
'
exit
'
,
(
code
)
=>
{
if
(
code
===
0
)
{
resolve
(
code
);
}
else
{
reject
(
code
);
}
})
})
}
}
saveAppLocal
(
app
:
App
)
{
if
(
app
.
local
)
{
localStorage
.
setItem
(
app
.
id
,
JSON
.
stringify
(
app
.
local
));
}
}
async
backupFiles
(
dir
:
string
,
backupDir
:
string
,
files
:
Iterable
<
string
>
)
{
for
(
let
file
of
files
)
{
await
new
Promise
(
async
(
resolve
,
reject
)
=>
{
let
srcPath
=
path
.
join
(
dir
,
file
);
let
backupPath
=
path
.
join
(
backupDir
,
file
);
await
this
.
createDirectory
(
path
.
dirname
(
backupPath
));
fs
.
unlink
(
backupPath
,
(
err
)
=>
{
fs
.
rename
(
srcPath
,
backupPath
,
resolve
);
});
});
}
}
async
restoreFiles
(
dir
:
string
,
backupDir
:
string
,
files
:
Iterable
<
string
>
)
{
for
(
let
file
of
files
)
{
await
new
Promise
((
resolve
,
reject
)
=>
{
let
backupPath
=
path
.
join
(
backupDir
,
file
);
let
srcPath
=
path
.
join
(
dir
,
file
);
fs
.
unlink
(
srcPath
,
(
err
)
=>
{
fs
.
rename
(
backupPath
,
srcPath
,
resolve
);
})
})
}
}
async
getChecksumFile
(
app
:
App
):
Promise
<
Map
<
string
,
string
>
>
{
let
checksumUrl
=
this
.
checksumURL
+
app
.
id
;
if
([
"
ygopro
"
,
'
desmume
'
].
includes
(
app
.
id
))
{
checksumUrl
=
this
.
checksumURL
+
app
.
id
+
"
-
"
+
process
.
platform
;
}
return
this
.
http
.
get
(
checksumUrl
)
.
map
((
response
)
=>
{
let
map
=
new
Map
<
string
,
string
>
();
for
(
let
line
of
response
.
text
().
split
(
'
\n
'
))
{
if
(
line
!==
""
)
{
let
[
checksum
,
filename
]
=
line
.
split
(
'
'
,
2
);
if
(
filename
.
endsWith
(
"
\\
"
)
||
filename
.
endsWith
(
"
/
"
))
{
map
.
set
(
filename
,
""
);
}
map
.
set
(
filename
,
checksum
);
}
}
return
map
;
}).
toPromise
();
}
deleteFile
(
file
:
string
):
Promise
<
string
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
fs
.
lstat
(
file
,
(
err
,
stats
)
=>
{
if
(
err
)
return
resolve
(
path
);
if
(
stats
.
isDirectory
())
{
fs
.
rmdir
(
file
,
(
err
)
=>
{
resolve
(
file
);
});
}
else
{
fs
.
unlink
(
file
,
(
err
)
=>
{
resolve
(
file
);
});
}
});
})
}
async
uninstall
(
app
:
App
)
{
if
(
app
.
isReady
())
{
app
.
status
.
status
=
"
uninstalling
"
;
let
appDir
=
app
.
local
!
.
path
;
let
files
=
Array
.
from
(
app
.
local
!
.
files
.
keys
()).
sort
().
reverse
();
app
.
status
.
total
=
files
.
length
;
for
(
let
file
of
files
)
{
app
.
status
.
progress
+=
1
;
await
this
.
deleteFile
(
path
.
join
(
appDir
,
file
));
}
if
(
app
.
parent
)
{
let
backupDir
=
path
.
join
(
path
.
dirname
(
appDir
),
"
backup
"
,
app
.
parent
.
id
)
let
fileSet
=
new
ComparableSet
(
files
);
let
parentSet
=
new
ComparableSet
(
Array
.
from
(
app
.
parent
.
local
!
.
files
.
keys
()));
let
difference
=
parentSet
.
intersection
(
fileSet
);
if
(
difference
)
{
this
.
restoreFiles
(
appDir
,
backupDir
,
Array
.
from
(
difference
))
}
}
app
.
local
=
null
;
localStorage
.
removeItem
(
app
.
id
);
}
}
}
\ No newline at end of file
app/lobby.component.ts
View file @
da3a1104
...
@@ -6,7 +6,6 @@ import {AppsService} from "./apps.service";
...
@@ -6,7 +6,6 @@ import {AppsService} from "./apps.service";
import
{
LoginService
}
from
"
./login.service
"
;
import
{
LoginService
}
from
"
./login.service
"
;
import
{
App
,
Category
}
from
"
./app
"
;
import
{
App
,
Category
}
from
"
./app
"
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
InstallService
}
from
"
./install.service
"
;
import
{
Http
,
URLSearchParams
}
from
"
@angular/http
"
;
import
{
Http
,
URLSearchParams
}
from
"
@angular/http
"
;
import
{
shell
}
from
"
electron
"
;
import
{
shell
}
from
"
electron
"
;
import
WebViewElement
=
Electron
.
WebViewElement
;
import
WebViewElement
=
Electron
.
WebViewElement
;
...
@@ -25,8 +24,7 @@ export class LobbyComponent implements OnInit {
...
@@ -25,8 +24,7 @@ export class LobbyComponent implements OnInit {
currentApp
:
App
;
currentApp
:
App
;
private
apps
:
Map
<
string
,
App
>
;
private
apps
:
Map
<
string
,
App
>
;
constructor
(
private
appsService
:
AppsService
,
private
loginService
:
LoginService
,
private
downloadService
:
DownloadService
,
constructor
(
private
appsService
:
AppsService
,
private
loginService
:
LoginService
)
{
private
installService
:
InstallService
,
private
http
:
Http
)
{
}
}
async
ngOnInit
()
{
async
ngOnInit
()
{
...
...
app/mycard.module.ts
View file @
da3a1104
...
@@ -14,7 +14,6 @@ import {AppsService} from "./apps.service";
...
@@ -14,7 +14,6 @@ import {AppsService} from "./apps.service";
import
{
SettingsService
}
from
"
./settings.sevices
"
;
import
{
SettingsService
}
from
"
./settings.sevices
"
;
import
{
LoginService
}
from
"
./login.service
"
;
import
{
LoginService
}
from
"
./login.service
"
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
InstallService
}
from
"
./install.service
"
;
@
NgModule
({
@
NgModule
({
imports
:
[
BrowserModule
,
FormsModule
,
ReactiveFormsModule
,
HttpModule
],
imports
:
[
BrowserModule
,
FormsModule
,
ReactiveFormsModule
,
HttpModule
],
...
@@ -25,7 +24,6 @@ import {InstallService} from "./install.service";
...
@@ -25,7 +24,6 @@ import {InstallService} from "./install.service";
bootstrap
:
[
MyCardComponent
],
bootstrap
:
[
MyCardComponent
],
providers
:
[
providers
:
[
AppsService
,
SettingsService
,
LoginService
,
DownloadService
,
AppsService
,
SettingsService
,
LoginService
,
DownloadService
,
InstallService
],
],
schemas
:
[
NO_ERRORS_SCHEMA
]
schemas
:
[
NO_ERRORS_SCHEMA
]
})
})
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment