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
b155bddd
Commit
b155bddd
authored
Dec 05, 2016
by
wudizhanche1000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
下载安装步骤
parent
6a33d0bc
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
170 additions
and
127 deletions
+170
-127
app/app-detail.component.html
app/app-detail.component.html
+4
-4
app/app-detail.component.ts
app/app-detail.component.ts
+1
-12
app/apps.service.ts
app/apps.service.ts
+62
-5
app/install.service.ts
app/install.service.ts
+54
-53
app/lobby.component.ts
app/lobby.component.ts
+0
-52
app/shared/ComparableSet.ts
app/shared/ComparableSet.ts
+47
-0
apps.json
apps.json
+2
-1
No files found.
app/app-detail.component.html
View file @
b155bddd
...
...
@@ -59,13 +59,13 @@
<tr
*ngFor=
"let mod of mods; let i = index"
>
<th
scope=
"row"
>
{{i + 1}}
</th>
<td>
{{mod.name}}
</td>
<td
*ngIf=
"mod.is
Installed
()"
>
<td
*ngIf=
"mod.is
Ready
()"
>
<button
i18n
type=
"button"
(click)=
"uninstall(mod)"
class=
"btn btn-danger btn-sm"
>
卸载
</button>
</td>
<td
*ngIf=
"!mod.isInstalled()"
>
<button
i18n
(click)=
"installMod(mod)"
type=
"button"
*ngIf=
"
mod.status.status==='init'
"
class=
"btn btn-primary btn-sm"
>
安装
</button>
<progress
*ngIf=
"mod.
status.status==='downloading'
"
class=
"progress progress-striped progress-animated"
value=
"{{mod.status.progress}}"
max=
"{{mod.status.total}}"
></progress>
<div
i18n
*ngIf=
"mod.
status.status==='waiting'
"
>
等待安装...
</div>
<button
i18n
(click)=
"installMod(mod)"
type=
"button"
*ngIf=
"
!mod.isInstalled()
"
class=
"btn btn-primary btn-sm"
>
安装
</button>
<progress
*ngIf=
"mod.
isDownloading()
"
class=
"progress progress-striped progress-animated"
value=
"{{mod.status.progress}}"
max=
"{{mod.status.total}}"
></progress>
<div
i18n
*ngIf=
"mod.
isWaiting()
"
>
等待安装...
</div>
</td>
</tr>
</tbody>
...
...
app/app-detail.component.ts
View file @
b155bddd
...
...
@@ -71,19 +71,8 @@ export class AppDetailComponent implements OnInit {
let
options
=
this
.
installOption
;
// if (options) {
// for (let reference of options.references) {
// if (reference.install && !reference.app.isInstalled()) {
// apps.push(reference.app);
// apps.push(...reference.app.findDependencies().filter((app) => {
// return !app.isInstalled()
// }))
// }
// }
// }
try
{
this
.
appsService
.
install
(
this
.
curren
tApp
,
options
);
await
this
.
appsService
.
install
(
targe
tApp
,
options
);
}
catch
(
e
)
{
console
.
error
(
e
);
new
Notification
(
targetApp
.
name
,
{
body
:
"
下载失败
"
});
...
...
app/apps.service.ts
View file @
b155bddd
...
...
@@ -14,6 +14,7 @@ import Timer = NodeJS.Timer;
import
{
DownloadService
}
from
"
./download.service
"
;
import
{
InstallOption
}
from
"
./install-option
"
;
import
{
InstallService
}
from
"
./install.service
"
;
import
{
ComparableSet
}
from
"
./shared/ComparableSet
"
;
const
Aria2
=
require
(
'
aria2
'
);
const
sudo
=
require
(
'
electron-sudo
'
);
...
...
@@ -116,6 +117,62 @@ export class AppsService {
return
apps
;
};
// async update(app: App) {
// const updateServer = "https://thief.mycard.moe/update/metalinks/";
//
// if (app.isReady() && app.local!.version != app.version) {
// let checksumMap = await this.installService.getChecksumFile(app)
//
// let latestFiles = new ComparableSet();
//
// }
//
// if (app.isInstalled() && app.version != (<AppLocal>app.local).version) {
// let checksumMap = await this.installService.getChecksumFile(app);
// let filesMap = (<AppLocal>app.local).files;
// let deleteList: string[] = [];
// let addList: string[] = [];
// let changeList: string[] = [];
// for (let [file,checksum] of filesMap) {
// let t = checksumMap.get(file);
// if (!t) {
// deleteList.push(file);
// } else if (t !== checksum) {
// changeList.push(file);
// }
// }
// for (let file of checksumMap.keys()) {
// if (!filesMap.has(file)) {
// changeList.push(file);
// }
// }
// let metalink = await this.http.post(updateServer + app.id, changeList).map((response) => response.text())
// .toPromise();
// let meta = new DOMParser().parseFromString(metalink, "text/xml");
// let filename = meta.getElementsByTagName('file')[0].getAttribute('name');
// let dir = path.join(path.dirname((<AppLocal>app.local).path), "downloading");
// let a = await this.downloadService.addMetalink(metalink, dir);
//
// for (let file of deleteList) {
// await this.installService.deleteFile(file);
// }
// (<AppLocal>app.local).version = app.version;
// (<AppLocal>app.local).files = checksumMap;
// localStorage.setItem(app.id, JSON.stringify(app.local));
// await this.installService.extract(path.join(dir, filename), (<AppLocal>app.local).path);
// let children = this.appsService.findChildren(app);
// for (let child of children) {
// if (child.isInstalled()) {
// await this.installService.uninstall(child, false);
// // this.installService.add(child, new InstallOption(child, path.dirname(((<AppLocal>app.local).path))));
// await this.installService.getComplete(child);
// console.log("282828")
// }
// }
//
// }
// }
async
install
(
app
:
App
,
option
:
InstallOption
)
{
const
addDownloadTask
=
async
(
app
:
App
,
dir
:
string
)
=>
{
let
metalinkUrl
=
app
.
download
;
...
...
@@ -145,8 +202,8 @@ export class AppsService {
let
currentUnit
=
Math
.
floor
(
Math
.
log
(
currentSpeed
)
/
Math
.
log
(
1024
));
console
.
log
(
currentSpeed
,
currentUnit
);
app
.
status
.
progressMessage
=
(
currentSpeed
/
1024
**
currentUnit
).
toFixed
(
1
)
+
"
"
+
speedUnit
[
currentUnit
];
}
else
{
app
.
status
.
progressMessage
=
''
;
}
else
{
app
.
status
.
progressMessage
=
''
;
}
this
.
ref
.
tick
();
},
(
error
)
=>
{
...
...
@@ -160,7 +217,9 @@ export class AppsService {
};
try
{
let
apps
:
App
[]
=
[];
let
dependencies
=
app
.
findDependencies
();
let
dependencies
=
app
.
findDependencies
().
filter
((
dependency
)
=>
{
return
!
dependency
.
isInstalled
();
});
apps
.
push
(...
dependencies
,
app
);
let
downloadPath
=
path
.
join
(
option
.
installLibrary
,
'
downloading
'
);
let
tasks
:
Promise
<
any
>
[]
=
[];
...
...
@@ -174,8 +233,6 @@ export class AppsService {
o
.
downloadFiles
=
result
.
files
;
this
.
installService
.
push
({
app
:
result
.
app
,
option
:
o
});
}
// this.installService.push({app: app, option: option})
}
catch
(
e
)
{
console
.
log
(
e
);
throw
e
;
...
...
app/install.service.ts
View file @
b155bddd
...
...
@@ -12,7 +12,7 @@ import * as fs from "fs";
import
{
EventEmitter
}
from
"
events
"
;
import
{
AppLocal
}
from
"
./app-local
"
;
import
{
Http
}
from
"
@angular/http
"
;
import
{
AppsService
}
from
"
./apps.service
"
;
import
{
ComparableSet
}
from
"
./shared/ComparableSet
"
import
ReadableStream
=
NodeJS
.
ReadableStream
;
import
{
Observable
,
Observer
}
from
"
rxjs/Rx
"
;
...
...
@@ -33,7 +33,8 @@ export class InstallService {
installingId
:
string
=
''
;
eventEmitter
:
EventEmitter
=
new
EventEmitter
();
checksumUri
=
"
https://thief.mycard.moe/checksums/
"
;
readonly
checksumURL
=
"
https://thief.mycard.moe/checksums/
"
;
readonly
updateServerURL
=
'
https://thief.mycard.moe/update/metalinks
'
;
installQueue
:
Map
<
string
,
InstallTask
>
=
new
Map
();
...
...
@@ -90,19 +91,18 @@ export class InstallService {
});
if
(
readyForInstall
)
{
let
option
=
task
.
option
;
let
installDir
=
option
.
installDir
;
// if (!app.isInstalled()) {
let
checksumFile
=
await
this
.
getChecksumFile
(
app
);
if
(
app
.
parent
)
{
let
conflictFiles
=
new
Set
<
string
>
();
let
parentFilesMap
=
app
.
parent
.
local
!
.
files
;
for
(
let
key
of
checksumFile
.
keys
())
{
if
(
parentFilesMap
.
has
(
key
))
{
conflictFiles
.
add
(
key
);
}
}
// 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
);
this
.
backupFiles
(
option
.
installDir
,
backupPath
,
conflictFiles
);
await
this
.
backupFiles
(
app
.
parent
.
local
!
.
path
,
backupPath
,
conflictFiles
);
}
}
let
allFiles
=
new
Set
(
checksumFile
.
keys
());
...
...
@@ -111,17 +111,14 @@ export class InstallService {
app
.
status
.
progress
=
0
;
// let timeNow = new Date().getTime();
for
(
let
file
of
option
.
downloadFiles
)
{
await
this
.
createDirectory
(
option
.
installDir
);
await
this
.
createDirectory
(
installDir
);
let
interval
=
setInterval
(()
=>
{
},
500
);
await
new
Promise
((
resolve
,
reject
)
=>
{
this
.
extract
(
file
,
option
.
installDir
).
subscribe
(
this
.
extract
(
file
,
installDir
).
subscribe
(
(
lastItem
:
string
)
=>
{
app
.
status
.
progress
+=
1
;
app
.
status
.
progressMessage
=
lastItem
;
// if (new Date().getTime() - timeNow > 500) {
// timeNow = new Date().getTime();
// }
},
(
error
)
=>
{
reject
(
error
);
...
...
@@ -132,9 +129,9 @@ export class InstallService {
});
clearInterval
(
interval
);
}
await
this
.
postInstall
(
app
,
option
.
installDir
);
await
this
.
postInstall
(
app
,
installDir
);
let
local
=
new
AppLocal
();
local
.
path
=
option
.
installDir
;
local
.
path
=
installDir
;
local
.
files
=
checksumFile
;
local
.
version
=
app
.
version
;
app
.
local
=
local
;
...
...
@@ -230,21 +227,35 @@ export class InstallService {
}
}
async
backupFiles
(
dir
:
string
,
backupPath
:
string
,
files
:
Iterable
<
string
>
)
{
await
this
.
createDirectory
(
backupPath
);
async
backupFiles
(
dir
:
string
,
backupDir
:
string
,
files
:
Iterable
<
string
>
)
{
for
(
let
file
of
files
)
{
await
new
Promise
((
resolve
,
reject
)
=>
{
let
oldPath
=
path
.
join
(
dir
,
file
);
let
newPath
=
path
.
join
(
backupPath
,
file
);
fs
.
rename
(
oldPath
,
newPath
,
resolve
);
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
.
checksumU
ri
+
app
.
id
;
let
checksumUrl
=
this
.
checksumU
RL
+
app
.
id
;
if
([
"
ygopro
"
,
'
desmume
'
].
includes
(
app
.
id
))
{
checksumUrl
=
this
.
checksumU
ri
+
app
.
id
+
"
-
"
+
process
.
platform
;
checksumUrl
=
this
.
checksumU
RL
+
app
.
id
+
"
-
"
+
process
.
platform
;
}
return
this
.
http
.
get
(
checksumUrl
)
.
map
((
response
)
=>
{
...
...
@@ -280,39 +291,29 @@ export class InstallService {
})
}
async
uninstall
(
app
:
App
,
restore
=
true
)
{
if
(
!
app
.
parent
)
{
// let children = this.appsService.findChildren(app);
// for (let child of children) {
// if (child.isInstalled()) {
// await this.uninstall(child);
// }
// }
}
let
files
=
Array
.
from
((
<
AppLocal
>
app
.
local
).
files
.
keys
()).
sort
().
reverse
();
for
(
let
file
of
files
)
{
let
oldFile
=
file
;
if
(
!
path
.
isAbsolute
(
file
))
{
oldFile
=
path
.
join
((
<
AppLocal
>
app
.
local
).
path
,
file
);
async
uninstall
(
app
:
App
)
{
if
(
app
.
isReady
())
{
let
appDir
=
app
.
local
!
.
path
;
let
files
=
Array
.
from
(
app
.
local
!
.
files
.
keys
()).
sort
().
reverse
();
for
(
let
file
of
files
)
{
this
.
deleteFile
(
path
.
join
(
appDir
,
file
));
}
if
(
restore
)
{
await
this
.
deleteFile
(
oldFile
);
if
(
app
.
parent
)
{
let
backFile
=
path
.
join
((
<
AppLocal
>
app
.
local
).
path
,
"
backup
"
,
file
);
await
new
Promise
((
resolve
,
reject
)
=>
{
fs
.
rename
(
backFile
,
oldFile
,
resolve
);
});
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
);
}
if
(
app
.
parent
)
{
await
this
.
deleteFile
(
path
.
join
((
<
AppLocal
>
app
.
local
).
path
,
"
backup
"
));
}
else
{
await
this
.
deleteFile
((
<
AppLocal
>
app
.
local
).
path
);
}
app
.
local
=
null
;
localStorage
.
removeItem
(
app
.
id
);
}
}
\ No newline at end of file
app/lobby.component.ts
View file @
b155bddd
...
...
@@ -43,9 +43,6 @@ export class LobbyComponent implements OnInit {
params
.
set
(
'
nickname
'
,
this
.
loginService
.
user
.
username
);
params
.
set
(
'
autojoin
'
,
this
.
currentApp
.
conference
+
'
@conference.mycard.moe
'
);
this
.
candy_url
=
url
;
// 尝试更新应用
this
.
updateApp
();
}
chooseApp
(
app
:
App
)
{
...
...
@@ -55,56 +52,7 @@ export class LobbyComponent implements OnInit {
}
}
async
updateApp
()
{
let
updateServer
=
"
https://thief.mycard.moe/update/metalinks/
"
;
let
checksumServer
=
"
https://thief.mycard.moe/checksums/
"
;
for
(
let
app
of
this
.
apps
.
values
())
{
if
(
app
.
isInstalled
()
&&
app
.
version
!=
(
<
AppLocal
>
app
.
local
).
version
)
{
let
checksumMap
=
await
this
.
installService
.
getChecksumFile
(
app
);
let
filesMap
=
(
<
AppLocal
>
app
.
local
).
files
;
let
deleteList
:
string
[]
=
[];
let
addList
:
string
[]
=
[];
let
changeList
:
string
[]
=
[];
for
(
let
[
file
,
checksum
]
of
filesMap
)
{
let
t
=
checksumMap
.
get
(
file
);
if
(
!
t
)
{
deleteList
.
push
(
file
);
}
else
if
(
t
!==
checksum
)
{
changeList
.
push
(
file
);
}
}
for
(
let
file
of
checksumMap
.
keys
())
{
if
(
!
filesMap
.
has
(
file
))
{
changeList
.
push
(
file
);
}
}
let
metalink
=
await
this
.
http
.
post
(
updateServer
+
app
.
id
,
changeList
).
map
((
response
)
=>
response
.
text
())
.
toPromise
();
let
meta
=
new
DOMParser
().
parseFromString
(
metalink
,
"
text/xml
"
);
let
filename
=
meta
.
getElementsByTagName
(
'
file
'
)[
0
].
getAttribute
(
'
name
'
);
let
dir
=
path
.
join
(
path
.
dirname
((
<
AppLocal
>
app
.
local
).
path
),
"
downloading
"
);
let
a
=
await
this
.
downloadService
.
addMetalink
(
metalink
,
dir
);
for
(
let
file
of
deleteList
)
{
await
this
.
installService
.
deleteFile
(
file
);
}
(
<
AppLocal
>
app
.
local
).
version
=
app
.
version
;
(
<
AppLocal
>
app
.
local
).
files
=
checksumMap
;
localStorage
.
setItem
(
app
.
id
,
JSON
.
stringify
(
app
.
local
));
await
this
.
installService
.
extract
(
path
.
join
(
dir
,
filename
),
(
<
AppLocal
>
app
.
local
).
path
);
let
children
=
this
.
appsService
.
findChildren
(
app
);
for
(
let
child
of
children
)
{
if
(
child
.
isInstalled
())
{
await
this
.
installService
.
uninstall
(
child
,
false
);
// this.installService.add(child, new InstallOption(child, path.dirname(((<AppLocal>app.local).path))));
await
this
.
installService
.
getComplete
(
child
);
console
.
log
(
"
282828
"
)
}
}
}
}
}
get
grouped_apps
()
{
...
...
app/shared/ComparableSet.ts
0 → 100644
View file @
b155bddd
/**
* Created by weijian on 2016/12/5.
*/
export
class
ComparableSet
<
T
>
extends
Set
<
T
>
{
constructor
(
values
?:
Iterable
<
T
>
)
{
if
(
values
)
{
super
(
values
);
}
else
{
super
();
}
}
isSuperset
(
subset
:
Set
<
T
>
)
{
for
(
var
elem
of
subset
)
{
if
(
!
this
.
has
(
elem
))
{
return
false
;
}
}
return
true
;
}
union
(
setB
:
Set
<
T
>
):
Set
<
T
>
{
var
union
=
new
Set
(
this
);
for
(
var
elem
of
setB
)
{
union
.
add
(
elem
);
}
return
union
;
}
intersection
(
setB
:
Set
<
T
>
):
Set
<
T
>
{
var
intersection
=
new
Set
();
for
(
var
elem
of
setB
)
{
if
(
this
.
has
(
elem
))
{
intersection
.
add
(
elem
);
}
}
return
intersection
;
}
difference
(
setB
:
Set
<
T
>
):
Set
<
T
>
{
var
difference
=
new
Set
(
this
);
for
(
var
elem
of
setB
)
{
difference
.
delete
(
elem
);
}
return
difference
;
}
}
apps.json
View file @
b155bddd
...
...
@@ -2071,7 +2071,8 @@
}
},
"version"
:
{
"darwin"
:
"1.06"
"win32"
:
"1.033.C-7"
,
"darwin"
:
"1.033.C-7"
},
"news"
:
[
{
...
...
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