auto sync, dep updates, other stuff
This commit is contained in:
parent
0577a0311a
commit
c76ff2ac36
12
debug.log
Normal file
12
debug.log
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[0813/143821.763:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143822.005:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143823.091:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143823.102:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143823.114:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143823.926:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143914.910:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143915.186:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143917.426:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143917.460:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143917.472:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143917.910:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
155
package-lock.json
generated
155
package-lock.json
generated
@ -1,27 +1,29 @@
|
|||||||
{
|
{
|
||||||
"name": "fanslysync-desktop",
|
"name": "fanslysync-desktop",
|
||||||
"version": "0.0.1",
|
"version": "0.1.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "fanslysync-desktop",
|
"name": "fanslysync-desktop",
|
||||||
"version": "0.0.1",
|
"version": "0.1.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||||
|
"@tauri-apps/plugin-autostart": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0"
|
"@tauri-apps/plugin-updater": "^2.0.0-rc.0",
|
||||||
|
"svelte-french-toast": "^1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/adapter-static": "^3.0.2",
|
"@sveltejs/adapter-static": "^3.0.2",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@tauri-apps/cli": "^2.0.0-rc.0",
|
"@tauri-apps/cli": "^2.0.0-rc.3",
|
||||||
"@types/eslint": "^8.56.7",
|
"@types/eslint": "^8.56.7",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.0.0",
|
||||||
@ -56,7 +58,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://npm.hep.gg/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
"resolved": "https://npm.hep.gg/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||||
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.24"
|
"@jridgewell/trace-mapping": "^0.3.24"
|
||||||
@ -610,7 +611,6 @@
|
|||||||
"version": "0.3.5",
|
"version": "0.3.5",
|
||||||
"resolved": "https://npm.hep.gg/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
"resolved": "https://npm.hep.gg/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/set-array": "^1.2.1",
|
"@jridgewell/set-array": "^1.2.1",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
@ -624,7 +624,6 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://npm.hep.gg/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
"resolved": "https://npm.hep.gg/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
@ -633,7 +632,6 @@
|
|||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://npm.hep.gg/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
"resolved": "https://npm.hep.gg/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
@ -641,14 +639,12 @@
|
|||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://npm.hep.gg/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
"resolved": "https://npm.hep.gg/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.25",
|
"version": "0.3.25",
|
||||||
"resolved": "https://npm.hep.gg/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
"resolved": "https://npm.hep.gg/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
@ -1020,9 +1016,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli": {
|
"node_modules/@tauri-apps/cli": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli/-/cli-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli/-/cli-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-X9N/R7e3zeTpU0HgQi2kaNYncMFoSTzXstnUyGOcKrJcCkR4ebbA2nYqhGvIPfglLKHNFRTZwfPNhixx2Ftxxg==",
|
"integrity": "sha512-iNF95pieBmverl1EmQyqh+fhcIClS544fN5Ex5lAbYLTiHZ/gm3lOfVBhF6NPaKd/sfLuy7K1tfDXlHztBfANw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tauri": "tauri.js"
|
"tauri": "tauri.js"
|
||||||
@ -1035,22 +1031,22 @@
|
|||||||
"url": "https://opencollective.com/tauri"
|
"url": "https://opencollective.com/tauri"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.0",
|
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.0",
|
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.0",
|
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.0",
|
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.0",
|
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.0",
|
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.0",
|
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.0",
|
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.0",
|
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.3",
|
||||||
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.0"
|
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-jpQc++6ESFUuBpoXvJNPTRtrmToMIByOynZ4K5SAwI9RkKUikSaDmlRZV0GisOVPT7TT08khk7MPtAQeFyjqwA==",
|
"integrity": "sha512-szYCSr/ChbCF+S6Wnr15TYpI2cZR07d+AQOiFGuScP0preM8Pbsk/sb0hfLwqzepjVFFNVWQba9sG7FEW2Y2XA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1064,9 +1060,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-EnqsgcNUwH29YjQ4JdBID5kILQQdIJgZ36VQgtju/BBvnd1lr+6Bswdk1/4y41hhAVz9WyHeMCnTH33CSKvNxw==",
|
"integrity": "sha512-BJv6EJOY1DJbRzVtfg8CcBAlnS5OjhBAc5YKjh4BT7EyOcop8HStBSxhL6yjWrUP7eLR1iIsW/uSehVJwzYIdQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1080,9 +1076,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-YKg/qThAmQYRToiV8lx/DvMf0VaUJAutIfv8ALq9Or4zdg7mZlAlKvF+7lZQQRmKhQ62+0gnoJS2HyN8feaagw==",
|
"integrity": "sha512-fwx805/xL4sF/EdMYqcUHQHzMYwo+OVTBTz5x/JWK8D57rnmLHAP+ZhnfFsZQLRo2QRT2l1Ye3bDyU+QRA1JFA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -1096,9 +1092,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-UnflWuNhH/u41GSmG1jm6qhWUM4o1AB463QCaf2fAjLo5GWiI78U6rJOOXZvOOmWIQuzsmAUZjNDORWW13+osA==",
|
"integrity": "sha512-3KauzO1Ls4kuY0nr82S4X8XFxlQAMN+Mqp8LLqvQ+PPMp92XQAkPH7osQdoHIEoW5gsE69U2JaiQ5tHSqNM9og==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1112,9 +1108,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-sWRaDyb332gtHWHr0KvoLzkzvXqRpZ0vpQYxKF2/mIZtaUuMtU56GmRwFVX4VjQYgWb3yWmzTr+tEKjCjXbjng==",
|
"integrity": "sha512-ngHS0foffm1xO5gqnDKGeYMKj8ceGmrFP5dDldoaaMQubw1SyFa0pRUjb7fZSYiO7F4SOSa8NYeMqlF9peZmnQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1128,9 +1124,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-1dokW+9ZfhwzwYz42jYR5A0/VnGoEGVW7HyN1N6KvHeL1FpSbh0LoTsDODjVjZSjXd62+Aac/stbJqBZChQWbA==",
|
"integrity": "sha512-0/am9pVvuUHGmz32M8ffz1fpLnc08j3nzcRe5wUdL2AxfT+wKMII+Dn99GtCVgcdDW4jSXDMRUwrBkGocGC2OA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1144,9 +1140,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-7tb34p3vLEGS4pGRpmxcz7eq37yD7DVe4XFfgj8ZO0KsaRBVivzNK2snNDLnd0dVZcx/lJjZc8Cf0B5W1/x/Jw==",
|
"integrity": "sha512-r7mRi8q8TqTFVjb9kAsU7IgwUgno2s8Ip4xwq9psQhlRE3JGEZQmSEcy1jqTjfl6KFh6lJcDR7l+9/EMhL/D3Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1160,9 +1156,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-Ilw3Gro8ZBew9yfBXcaET9lLj0g4jehWDMH6j2Wdje1rnvBbQShMaSn3WNMfJypyet5nqM88nGA3YipzmVcIBA==",
|
"integrity": "sha512-2J6KjmDIQCw6HF1X6/yPcd+JLl7pxrH2zVMGmNllaoWhHeByvRobqFWnT7gcdHaA3dGTo432CwWvOgTgrINQpQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1176,9 +1172,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-AWzgDlvv0BssWH3aNsDXLRkKbGynWdm5X6DenSQKtZm5dmDBZsNlZRMgkyPb8WSHK/7ARznKs2OdnkuHWuh9ww==",
|
"integrity": "sha512-8q75CsHDSEDdgi6xPwim+BaQZFCswK2Dn/qL38V3Mh9kmVvC8oGJMPC66bC20dF+v3KWeFm2FNNGQqOSXCveHg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -1192,9 +1188,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.3",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.3.tgz",
|
||||||
"integrity": "sha512-zmXDUkBmzZ6lk6jT6AoOAE2w+kmkLX5uf/vaJHHzE6WsrZ6UymH0HTLwbRXhaplvpnzXGVyLuSlv3/BK6Q69aQ==",
|
"integrity": "sha512-qeBRJYalahxEXolekcpZJ/HBrIJacG2NWJBGhhi797mIwnbmlpbHMc8blIJtNNNwVUb2BjXuxKQVfojQ5YYrcg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1207,6 +1203,14 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tauri-apps/plugin-autostart": {
|
||||||
|
"version": "2.0.0-rc.0",
|
||||||
|
"resolved": "https://npm.hep.gg/@tauri-apps/plugin-autostart/-/plugin-autostart-2.0.0-rc.0.tgz",
|
||||||
|
"integrity": "sha512-V49lm++vhrMPPDGMtmOcbJLF4TYu78ZmAiMhyd4FFnbYlgin6ZTjiMCFEl4JKVy2lqP3C8DQvXf/gkUMuER7Iw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "^2.0.0-rc.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tauri-apps/plugin-clipboard-manager": {
|
"node_modules/@tauri-apps/plugin-clipboard-manager": {
|
||||||
"version": "2.0.0-rc.0",
|
"version": "2.0.0-rc.0",
|
||||||
"resolved": "https://npm.hep.gg/@tauri-apps/plugin-clipboard-manager/-/plugin-clipboard-manager-2.0.0-rc.0.tgz",
|
"resolved": "https://npm.hep.gg/@tauri-apps/plugin-clipboard-manager/-/plugin-clipboard-manager-2.0.0-rc.0.tgz",
|
||||||
@ -1274,8 +1278,7 @@
|
|||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://npm.hep.gg/@types/estree/-/estree-1.0.5.tgz",
|
"resolved": "https://npm.hep.gg/@types/estree/-/estree-1.0.5.tgz",
|
||||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
@ -1511,7 +1514,6 @@
|
|||||||
"version": "8.12.1",
|
"version": "8.12.1",
|
||||||
"resolved": "https://npm.hep.gg/acorn/-/acorn-8.12.1.tgz",
|
"resolved": "https://npm.hep.gg/acorn/-/acorn-8.12.1.tgz",
|
||||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@ -1603,7 +1605,6 @@
|
|||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://npm.hep.gg/aria-query/-/aria-query-5.3.0.tgz",
|
"resolved": "https://npm.hep.gg/aria-query/-/aria-query-5.3.0.tgz",
|
||||||
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dequal": "^2.0.3"
|
"dequal": "^2.0.3"
|
||||||
}
|
}
|
||||||
@ -1658,7 +1659,6 @@
|
|||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://npm.hep.gg/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://npm.hep.gg/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
@ -1838,7 +1838,6 @@
|
|||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://npm.hep.gg/code-red/-/code-red-1.0.4.tgz",
|
"resolved": "https://npm.hep.gg/code-red/-/code-red-1.0.4.tgz",
|
||||||
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
|
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||||
"@types/estree": "^1.0.1",
|
"@types/estree": "^1.0.1",
|
||||||
@ -1907,7 +1906,6 @@
|
|||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://npm.hep.gg/css-tree/-/css-tree-2.3.1.tgz",
|
"resolved": "https://npm.hep.gg/css-tree/-/css-tree-2.3.1.tgz",
|
||||||
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mdn-data": "2.0.30",
|
"mdn-data": "2.0.30",
|
||||||
"source-map-js": "^1.0.1"
|
"source-map-js": "^1.0.1"
|
||||||
@ -1964,7 +1962,6 @@
|
|||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://npm.hep.gg/dequal/-/dequal-2.0.3.tgz",
|
"resolved": "https://npm.hep.gg/dequal/-/dequal-2.0.3.tgz",
|
||||||
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
@ -2291,7 +2288,6 @@
|
|||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://npm.hep.gg/estree-walker/-/estree-walker-3.0.3.tgz",
|
"resolved": "https://npm.hep.gg/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||||
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "^1.0.0"
|
"@types/estree": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -2725,7 +2721,6 @@
|
|||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://npm.hep.gg/is-reference/-/is-reference-3.0.2.tgz",
|
"resolved": "https://npm.hep.gg/is-reference/-/is-reference-3.0.2.tgz",
|
||||||
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
|
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "*"
|
"@types/estree": "*"
|
||||||
}
|
}
|
||||||
@ -2845,8 +2840,7 @@
|
|||||||
"node_modules/locate-character": {
|
"node_modules/locate-character": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://npm.hep.gg/locate-character/-/locate-character-3.0.0.tgz",
|
"resolved": "https://npm.hep.gg/locate-character/-/locate-character-3.0.0.tgz",
|
||||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
@ -2879,7 +2873,6 @@
|
|||||||
"version": "0.30.10",
|
"version": "0.30.10",
|
||||||
"resolved": "https://npm.hep.gg/magic-string/-/magic-string-0.30.10.tgz",
|
"resolved": "https://npm.hep.gg/magic-string/-/magic-string-0.30.10.tgz",
|
||||||
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
}
|
}
|
||||||
@ -2887,8 +2880,7 @@
|
|||||||
"node_modules/mdn-data": {
|
"node_modules/mdn-data": {
|
||||||
"version": "2.0.30",
|
"version": "2.0.30",
|
||||||
"resolved": "https://npm.hep.gg/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://npm.hep.gg/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
@ -3200,7 +3192,6 @@
|
|||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://npm.hep.gg/periscopic/-/periscopic-3.1.0.tgz",
|
"resolved": "https://npm.hep.gg/periscopic/-/periscopic-3.1.0.tgz",
|
||||||
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
|
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "^1.0.0",
|
||||||
"estree-walker": "^3.0.0",
|
"estree-walker": "^3.0.0",
|
||||||
@ -3729,7 +3720,6 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://npm.hep.gg/source-map-js/-/source-map-js-1.2.0.tgz",
|
"resolved": "https://npm.hep.gg/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -3942,7 +3932,6 @@
|
|||||||
"version": "4.2.18",
|
"version": "4.2.18",
|
||||||
"resolved": "https://npm.hep.gg/svelte/-/svelte-4.2.18.tgz",
|
"resolved": "https://npm.hep.gg/svelte/-/svelte-4.2.18.tgz",
|
||||||
"integrity": "sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==",
|
"integrity": "sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.1",
|
"@ampproject/remapping": "^2.2.1",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||||
@ -4055,6 +4044,17 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-french-toast": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://npm.hep.gg/svelte-french-toast/-/svelte-french-toast-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"svelte-writable-derived": "^3.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"svelte": "^3.57.0 || ^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte-hmr": {
|
"node_modules/svelte-hmr": {
|
||||||
"version": "0.16.0",
|
"version": "0.16.0",
|
||||||
"resolved": "https://npm.hep.gg/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
|
"resolved": "https://npm.hep.gg/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
|
||||||
@ -4129,6 +4129,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-writable-derived": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://npm.hep.gg/svelte-writable-derived/-/svelte-writable-derived-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://ko-fi.com/pixievoltno1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"svelte": "^3.2.1 || ^4.0.0-next.1 || ^5.0.0-next.94"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.4.6",
|
"version": "3.4.6",
|
||||||
"resolved": "https://npm.hep.gg/tailwindcss/-/tailwindcss-3.4.6.tgz",
|
"resolved": "https://npm.hep.gg/tailwindcss/-/tailwindcss-3.4.6.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "fanslysync-desktop",
|
"name": "fanslysync-desktop",
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
@ -17,7 +17,7 @@
|
|||||||
"@sveltejs/adapter-static": "^3.0.2",
|
"@sveltejs/adapter-static": "^3.0.2",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@tauri-apps/cli": "^2.0.0-rc.0",
|
"@tauri-apps/cli": "^2.0.0-rc.3",
|
||||||
"@types/eslint": "^8.56.7",
|
"@types/eslint": "^8.56.7",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^9.0.0",
|
"eslint": "^9.0.0",
|
||||||
@ -38,11 +38,13 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||||
|
"@tauri-apps/plugin-autostart": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
||||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0"
|
"@tauri-apps/plugin-updater": "^2.0.0-rc.0",
|
||||||
|
"svelte-french-toast": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
391
src-tauri/Cargo.lock
generated
391
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "app"
|
name = "app"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["SticksDev"]
|
authors = ["SticksDev"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@ -12,26 +12,29 @@ rust-version = "1.80"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
tauri-build = { version = "2.0.0-rc.2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tauri = { version = "2.0.0-rc", features = [] }
|
tauri = { version = "2.0.0-rc.2", features = [] }
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
reqwest = { version = "0.11.18", features = ["json"] }
|
reqwest = { version = "0.11.18", features = ["json"] }
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
tokio = { version = "1.29.1", features = ["full"] }
|
tokio = { version = "1.29.1", features = ["full"] }
|
||||||
tokio-macros = "2.3.0"
|
tokio-macros = "2.3.0"
|
||||||
tauri-plugin-os = "2.0.0-alpha.2"
|
tauri-plugin-os = { version = "2.0.0-rc" }
|
||||||
tauri-plugin-dialog = "2.0.0-alpha.2"
|
tauri-plugin-dialog = { version = "2.0.0-rc" }
|
||||||
tauri-plugin-clipboard-manager = "2.0.0-alpha.2"
|
tauri-plugin-clipboard-manager = { version = "2.0.0-rc" }
|
||||||
tauri-plugin-notification = "2.0.0-alpha.3"
|
tauri-plugin-notification = { version = "2.0.0-rc" }
|
||||||
tauri-plugin-updater = "2.0.0-alpha.3"
|
tauri-plugin-updater = { version = "2.0.0-rc" }
|
||||||
tauri-plugin-log = "2.0.0-rc.0"
|
tauri-plugin-log = { version = "2.0.0-rc" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||||
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
||||||
# DO NOT REMOVE!!
|
# DO NOT REMOVE!!
|
||||||
custom-protocol = [ "tauri/custom-protocol" ]
|
custom-protocol = [ "tauri/custom-protocol" ]
|
||||||
|
|
||||||
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
|
tauri-plugin-autostart = "2.0.0-rc.0"
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
"identifier": "migrated",
|
"identifier": "migrated",
|
||||||
"description": "permissions that were migrated from v1",
|
"description": "permissions that were migrated from v1",
|
||||||
"local": true,
|
"local": true,
|
||||||
"windows": [
|
"windows": ["main"],
|
||||||
"main"
|
|
||||||
],
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"core:default",
|
"core:default",
|
||||||
"dialog:allow-message",
|
"dialog:allow-message",
|
||||||
@ -28,6 +26,7 @@
|
|||||||
"clipboard-manager:default",
|
"clipboard-manager:default",
|
||||||
"notification:default",
|
"notification:default",
|
||||||
"updater:default",
|
"updater:default",
|
||||||
"log:default"
|
"log:default",
|
||||||
|
"autostart:default"
|
||||||
]
|
]
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default"]}}
|
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default","autostart:default"]}}
|
@ -171,6 +171,55 @@
|
|||||||
},
|
},
|
||||||
"Identifier": {
|
"Identifier": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:default"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-disable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-enable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-is-enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-disable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-enable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-is-enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -171,6 +171,55 @@
|
|||||||
},
|
},
|
||||||
"Identifier": {
|
"Identifier": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:default"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-disable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-enable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:allow-is-enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-disable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-enable"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"autostart:deny-is-enabled"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -3,6 +3,7 @@ use crate::{
|
|||||||
structs::{FanslyAccountResponse, FanslyBaseResponse, SyncDataResponse},
|
structs::{FanslyAccountResponse, FanslyBaseResponse, SyncDataResponse},
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use serde_json::Value;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -26,9 +27,34 @@ pub async fn fansly_get_me() -> Result<FanslyBaseResponse<FanslyAccountResponse>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn fansly_sync() -> Result<SyncDataResponse, String> {
|
pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
||||||
let fansly = FANSLY.lock().await;
|
let fansly = FANSLY.lock().await;
|
||||||
let response = fansly.sync().await;
|
let response = fansly.sync(auto).await;
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(response) => Ok(response),
|
||||||
|
Err(e) => Err(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn fansly_upload_auto_sync_data(
|
||||||
|
data: SyncDataResponse,
|
||||||
|
token: String,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||||
|
let response = fansly.upload_auto_sync_data(data, token).await;
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(e) => Err(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn fansly_check_sync_token(token: String) -> Result<Value, String> {
|
||||||
|
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||||
|
let response = fansly.check_sync_token(token).await;
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
Ok(response) => Ok(response),
|
Ok(response) => Ok(response),
|
||||||
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
|||||||
|
|
||||||
use crate::structs::{FanslyFollowersResponse, Subscription};
|
use crate::structs::{FanslyFollowersResponse, Subscription};
|
||||||
|
|
||||||
const CURRENT_VERSION: i32 = 1; // Set the current version of the config
|
const CURRENT_VERSION: i32 = 2; // Set the current version of the config
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct SyncData {
|
pub struct SyncData {
|
||||||
@ -18,6 +18,8 @@ pub struct Config {
|
|||||||
pub version: i32, // Add a version field to the config (1, 2, 3, etc.)
|
pub version: i32, // Add a version field to the config (1, 2, 3, etc.)
|
||||||
pub is_first_run: bool,
|
pub is_first_run: bool,
|
||||||
pub fansly_token: String,
|
pub fansly_token: String,
|
||||||
|
pub auto_sync_enabled: bool,
|
||||||
|
pub sync_token: String,
|
||||||
pub sync_interval: u64,
|
pub sync_interval: u64,
|
||||||
pub last_sync: u64,
|
pub last_sync: u64,
|
||||||
pub last_sync_data: SyncData,
|
pub last_sync_data: SyncData,
|
||||||
@ -31,6 +33,8 @@ impl Default for Config {
|
|||||||
fansly_token: String::new(), // Fansly token is stored as a string
|
fansly_token: String::new(), // Fansly token is stored as a string
|
||||||
sync_interval: 1, // Every hour - sync interval is interpreted as hours
|
sync_interval: 1, // Every hour - sync interval is interpreted as hours
|
||||||
last_sync: 0, // Last sync time is stored as a UNIX timestamp
|
last_sync: 0, // Last sync time is stored as a UNIX timestamp
|
||||||
|
auto_sync_enabled: false, // Auto sync is disabled by default
|
||||||
|
sync_token: String::new(), // Sync token is stored as a string
|
||||||
last_sync_data: SyncData {
|
last_sync_data: SyncData {
|
||||||
followers: Vec::new(),
|
followers: Vec::new(),
|
||||||
subscribers: Vec::new(),
|
subscribers: Vec::new(),
|
||||||
@ -42,17 +46,89 @@ impl Default for Config {
|
|||||||
impl Config {
|
impl Config {
|
||||||
pub fn load_or_create(path: &Path) -> io::Result<Self> {
|
pub fn load_or_create(path: &Path) -> io::Result<Self> {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
let mut config: Self = serde_json::from_str(std::fs::read_to_string(path)?.as_str())
|
let config_result: Result<Self, _> =
|
||||||
.map_err(|e| {
|
serde_json::from_str(&std::fs::read_to_string(path)?);
|
||||||
io::Error::new(
|
let config = match config_result {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(_) => {
|
||||||
|
// Load raw JSON and attempt to parse it as a JSON object
|
||||||
|
let config_raw = std::fs::read_to_string(path)?;
|
||||||
|
let config_json: serde_json::Value = serde_json::from_str(&config_raw)?;
|
||||||
|
|
||||||
|
println!("[config::migrate] Migrating config file to latest version...");
|
||||||
|
println!(
|
||||||
|
"[config::migrate] [DEBUG] config is_object: {}",
|
||||||
|
config_json.is_object()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the JSON object is valid, if not, return an error
|
||||||
|
if !config_json.is_object() {
|
||||||
|
println!(
|
||||||
|
"[config::migrate] [ERROR] Found invalid JSON object in config file"
|
||||||
|
);
|
||||||
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidData,
|
io::ErrorKind::InvalidData,
|
||||||
format!("Could not parse config file: {}", e),
|
"Tried to migrate a config file, but found an invalid JSON object",
|
||||||
)
|
));
|
||||||
})?;
|
}
|
||||||
if config.version != CURRENT_VERSION {
|
|
||||||
|
// Get the version field from the JSON object
|
||||||
|
let version = config_json["version"].as_i64().unwrap_or(0) as i32;
|
||||||
|
|
||||||
|
// Check if the version field is a valid integer, if not, return an error
|
||||||
|
if version == 0 {
|
||||||
|
println!(
|
||||||
|
"[config::migrate] [ERROR] Found invalid version field in config JSON"
|
||||||
|
);
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
"Tried to migrate a config file, but found an invalid version field",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"[config::migrate] Found version field in config JSON: {}",
|
||||||
|
version
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now create a new Config object and set the version field to the value we found
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.version = version;
|
||||||
|
|
||||||
|
// Retain important fields from the JSON object
|
||||||
|
config.is_first_run = config_json["is_first_run"].as_bool().unwrap_or(true);
|
||||||
|
config.fansly_token = config_json["fansly_token"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string();
|
||||||
|
config.sync_token =
|
||||||
|
config_json["sync_token"].as_str().unwrap_or("").to_string();
|
||||||
|
config.sync_interval =
|
||||||
|
config_json["sync_interval"].as_i64().unwrap_or(1) as u64;
|
||||||
|
|
||||||
|
// Run migrations on the config object and save it
|
||||||
config = config.migrate()?;
|
config = config.migrate()?;
|
||||||
config.save(path)?;
|
config.save(path)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"[config::migrate] Successfully migrated config file to latest version"
|
||||||
|
);
|
||||||
|
// Recursively call load_or_create to load the migrated config
|
||||||
|
return Config::load_or_create(path);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if config.version != CURRENT_VERSION {
|
||||||
|
// Should have been migrated by now, error out because it wasn't
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!(
|
||||||
|
"Config version mismatch: expected {}, got {}. Please try removing the config file and restarting the application.",
|
||||||
|
CURRENT_VERSION, config.version
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
} else {
|
} else {
|
||||||
let saved_config = Config::default().save(path);
|
let saved_config = Config::default().save(path);
|
||||||
@ -66,8 +142,12 @@ impl Config {
|
|||||||
while self.version < CURRENT_VERSION {
|
while self.version < CURRENT_VERSION {
|
||||||
self = match self.version {
|
self = match self.version {
|
||||||
1 => {
|
1 => {
|
||||||
// If we're on version 1, migrate to version 2 (not implemented)
|
// Migrate from version 1 to version 2
|
||||||
self.version += 1;
|
self.version = 2;
|
||||||
|
self.auto_sync_enabled = false;
|
||||||
|
self.sync_token = String::new();
|
||||||
|
self.sync_interval = 1;
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -5,6 +5,7 @@ use crate::structs::{
|
|||||||
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
||||||
};
|
};
|
||||||
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
pub struct Fansly {
|
pub struct Fansly {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
@ -195,7 +196,73 @@ impl Fansly {
|
|||||||
Ok(format!("https://paste.hep.gg/{}", key))
|
Ok(format!("https://paste.hep.gg/{}", key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sync(&self) -> Result<SyncDataResponse, String> {
|
pub async fn upload_auto_sync_data(
|
||||||
|
&self,
|
||||||
|
data: SyncDataResponse,
|
||||||
|
token: String,
|
||||||
|
) -> Result<(), reqwest::Error> {
|
||||||
|
let url = "http://localhost:5001/sync";
|
||||||
|
|
||||||
|
// Set our content type to application/json
|
||||||
|
let mut headers = reqwest::header::HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
reqwest::header::CONTENT_TYPE,
|
||||||
|
"application/json".parse().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add our auth token to the headers
|
||||||
|
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.post(url)
|
||||||
|
.headers(headers)
|
||||||
|
.json(&data)
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !response.status().is_success() {
|
||||||
|
eprintln!("[sync::process::upload_auto_sync_data] Failed to upload sync data.");
|
||||||
|
return Err(response.error_for_status().unwrap_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check_sync_token(&self, token: String) -> Result<Value, reqwest::Error> {
|
||||||
|
// Check if the token is valid (GET /checkSyncToken with Authorization header)
|
||||||
|
// If it is, return the data back from the API
|
||||||
|
// If it isn't, return an error
|
||||||
|
let url = "http://localhost:5001/checkSyncToken";
|
||||||
|
|
||||||
|
// Set our content type to application/json
|
||||||
|
let mut headers = reqwest::header::HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
reqwest::header::CONTENT_TYPE,
|
||||||
|
"application/json".parse().unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add our auth token to the headers
|
||||||
|
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||||
|
|
||||||
|
let response = self.client.get(url).headers(headers).send().await;
|
||||||
|
|
||||||
|
// If successful, return the data, otherwise return an error
|
||||||
|
match response {
|
||||||
|
Ok(response) => {
|
||||||
|
if !response.status().is_success() {
|
||||||
|
eprintln!("[sync::process::check_sync_token] Failed to check sync token.");
|
||||||
|
return Err(response.error_for_status().unwrap_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
let json: serde_json::Value = response.json().await?;
|
||||||
|
Ok(json)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn sync(&self, auto: bool) -> Result<SyncDataResponse, String> {
|
||||||
// Fetch profile
|
// Fetch profile
|
||||||
println!("[sync::process] Fetching profile...");
|
println!("[sync::process] Fetching profile...");
|
||||||
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
||||||
@ -280,6 +347,7 @@ impl Fansly {
|
|||||||
println!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
println!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
||||||
|
|
||||||
// Upload sync data to paste.hep.gg
|
// Upload sync data to paste.hep.gg
|
||||||
|
if !auto {
|
||||||
let paste_url = self
|
let paste_url = self
|
||||||
.upload_sync_data(SyncDataResponse {
|
.upload_sync_data(SyncDataResponse {
|
||||||
followers: followers.clone(),
|
followers: followers.clone(),
|
||||||
@ -295,5 +363,13 @@ impl Fansly {
|
|||||||
subscribers,
|
subscribers,
|
||||||
sync_data_url: paste_url,
|
sync_data_url: paste_url,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
// Return JSON of what we fetched
|
||||||
|
Ok(SyncDataResponse {
|
||||||
|
followers,
|
||||||
|
subscribers,
|
||||||
|
sync_data_url: "".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,12 @@ use std::fs;
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use commands::config::{get_config, init_config, save_config};
|
use commands::config::{get_config, init_config, save_config};
|
||||||
use commands::fansly::{fansly_get_me, fansly_set_token, fansly_sync};
|
use commands::fansly::{
|
||||||
|
fansly_check_sync_token, fansly_get_me, fansly_set_token, fansly_sync,
|
||||||
|
fansly_upload_auto_sync_data,
|
||||||
|
};
|
||||||
use commands::utils::quit;
|
use commands::utils::quit;
|
||||||
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
use tauri_plugin_log::{Target, TargetKind};
|
use tauri_plugin_log::{Target, TargetKind};
|
||||||
|
|
||||||
fn get_log_path() -> io::Result<String> {
|
fn get_log_path() -> io::Result<String> {
|
||||||
@ -31,6 +35,10 @@ fn get_log_path() -> io::Result<String> {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_autostart::init(
|
||||||
|
MacosLauncher::LaunchAgent,
|
||||||
|
None,
|
||||||
|
))
|
||||||
.plugin(tauri_plugin_log::Builder::new().build())
|
.plugin(tauri_plugin_log::Builder::new().build())
|
||||||
.plugin(tauri_plugin_notification::init())
|
.plugin(tauri_plugin_notification::init())
|
||||||
.plugin(tauri_plugin_clipboard_manager::init())
|
.plugin(tauri_plugin_clipboard_manager::init())
|
||||||
@ -55,7 +63,9 @@ async fn main() {
|
|||||||
quit,
|
quit,
|
||||||
fansly_set_token,
|
fansly_set_token,
|
||||||
fansly_get_me,
|
fansly_get_me,
|
||||||
fansly_sync
|
fansly_sync,
|
||||||
|
fansly_upload_auto_sync_data,
|
||||||
|
fansly_check_sync_token
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -2,6 +2,8 @@ export type Config = {
|
|||||||
version: number;
|
version: number;
|
||||||
is_first_run: boolean;
|
is_first_run: boolean;
|
||||||
fansly_token: string;
|
fansly_token: string;
|
||||||
|
auto_sync_enabled: boolean;
|
||||||
|
sync_token: string;
|
||||||
sync_interval: number;
|
sync_interval: number;
|
||||||
last_sync: number;
|
last_sync: number;
|
||||||
last_sync_data: SyncData;
|
last_sync_data: SyncData;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
|
import { Toaster } from 'svelte-french-toast';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Toaster position='bottom-center' />
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -87,8 +87,20 @@
|
|||||||
info(`[FanslySync::init] Not first run. Setting Fansly token...`);
|
info(`[FanslySync::init] Not first run. Setting Fansly token...`);
|
||||||
await invoke('fansly_set_token', { token: config.fansly_token });
|
await invoke('fansly_set_token', { token: config.fansly_token });
|
||||||
info(`[FanslySync::init] Fansly token set.`);
|
info(`[FanslySync::init] Fansly token set.`);
|
||||||
info(`[FanslySync::init] Initialization complete. Redirecting to /home...`);
|
info(`[FanslySync::init] Checking token validity...`);
|
||||||
window.location.href = '/home';
|
|
||||||
|
const [valid, validError] = await awaiter(invoke('fansly_get_me'));
|
||||||
|
if (validError) {
|
||||||
|
error(`[FanslySync::init] Token invalid. Redirecting to /setup...`);
|
||||||
|
await message(
|
||||||
|
`Your Fansly token is invalid. Please re-enter your token in the setup page.`,
|
||||||
|
{ title: 'FanslySync | Token Invalid', kind: 'error' }
|
||||||
|
);
|
||||||
|
window.location.href = '/setup';
|
||||||
|
} else {
|
||||||
|
info(`[FanslySync::init] Token valid. Redirecting to /dashboard...`);
|
||||||
|
window.location.href = '/dashboard';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import { awaiter } from '$lib/utils';
|
import { awaiter } from '$lib/utils';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import type { Config, SyncData } from '$lib/types';
|
import type { Config, SyncData } from '$lib/types';
|
||||||
import { slide } from 'svelte/transition';
|
import { fade, fly, slide } from 'svelte/transition';
|
||||||
import { sendNotification } from '@tauri-apps/plugin-notification';
|
import { sendNotification } from '@tauri-apps/plugin-notification';
|
||||||
import { platform } from '@tauri-apps/plugin-os';
|
import { platform } from '@tauri-apps/plugin-os';
|
||||||
import { check, Update } from '@tauri-apps/plugin-updater';
|
import { check, Update } from '@tauri-apps/plugin-updater';
|
||||||
@ -11,6 +11,8 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { ask, message } from '@tauri-apps/plugin-dialog';
|
import { ask, message } from '@tauri-apps/plugin-dialog';
|
||||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||||
|
import { isEnabled, enable } from '@tauri-apps/plugin-autostart';
|
||||||
|
import { toast } from 'svelte-french-toast';
|
||||||
|
|
||||||
let loadingSync = true;
|
let loadingSync = true;
|
||||||
let upToDate: boolean | null = null;
|
let upToDate: boolean | null = null;
|
||||||
@ -28,7 +30,20 @@
|
|||||||
message: ''
|
message: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let isAutoSyncConfigModalOpen = false;
|
||||||
|
let canSave = false;
|
||||||
let config: Config | null = null;
|
let config: Config | null = null;
|
||||||
|
let syncInterval: number | null = null;
|
||||||
|
|
||||||
|
let autoSyncConfig = {
|
||||||
|
interval: 0,
|
||||||
|
syncToken: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
let autoSyncConfigState = {
|
||||||
|
validatingToken: false,
|
||||||
|
tokenValid: false
|
||||||
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
info(`[FanslySync::page_init:home] onMount() called. Starting page initialization...`);
|
info(`[FanslySync::page_init:home] onMount() called. Starting page initialization...`);
|
||||||
@ -55,6 +70,8 @@
|
|||||||
`[FanslySync::page_init:home] Configuration initialized successfully. Checking for updates...`
|
`[FanslySync::page_init:home] Configuration initialized successfully. Checking for updates...`
|
||||||
);
|
);
|
||||||
config = configData;
|
config = configData;
|
||||||
|
autoSyncConfig.interval = config.sync_interval;
|
||||||
|
autoSyncConfig.syncToken = config.sync_token;
|
||||||
loadingSync = false;
|
loadingSync = false;
|
||||||
|
|
||||||
const updateStatus = await check();
|
const updateStatus = await check();
|
||||||
@ -72,19 +89,80 @@
|
|||||||
`[FanslySync::page_init:home] App and Tauri versions fetched. We are running App version: ${versionData.appVersion}, atop Tauri version: ${versionData.tauriVersion}`
|
`[FanslySync::page_init:home] App and Tauri versions fetched. We are running App version: ${versionData.appVersion}, atop Tauri version: ${versionData.tauriVersion}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
info(`[FanslySync::page_init:home] Setting up autosync interval...`);
|
||||||
|
syncInterval = setInterval(
|
||||||
|
async () => {
|
||||||
|
if (config?.auto_sync_enabled) {
|
||||||
|
info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
||||||
|
const nextIntervalTime = new Date(
|
||||||
|
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
|
);
|
||||||
|
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
||||||
|
const returnedData = await syncNow(true);
|
||||||
|
if (!returnedData || returnedData === null) {
|
||||||
|
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||||
|
|
||||||
|
// Send error notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
|
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
info(
|
||||||
|
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||||
|
);
|
||||||
|
|
||||||
|
const [_, uploadErr] = await awaiter(
|
||||||
|
invoke('fansly_upload_auto_sync_data', {
|
||||||
|
token: config?.sync_token,
|
||||||
|
data: returnedData
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (uploadErr) {
|
||||||
|
error(
|
||||||
|
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Send error notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
|
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send success notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Successful!',
|
||||||
|
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
|
);
|
||||||
|
|
||||||
|
info(`[FanslySync::page_init:home] Autosync interval set successfully.`);
|
||||||
info(`[FanslySync::page_init:home] Page initialization completed successfully.`);
|
info(`[FanslySync::page_init:home] Page initialization completed successfully.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function syncNow() {
|
async function syncNow(auto: boolean = false) {
|
||||||
info(`[FanslySync::syncNow] Starting manual sync...`);
|
info(`[FanslySync::syncNow] Starting manual sync...`);
|
||||||
|
|
||||||
syncState.error = false;
|
syncState.error = false;
|
||||||
syncState.success = false;
|
syncState.success = false;
|
||||||
syncState.syncing = true;
|
syncState.syncing = true;
|
||||||
syncState.show = true;
|
syncState.show = !auto;
|
||||||
|
|
||||||
const [syncData, syncError] = await awaiter(invoke('fansly_sync') as Promise<SyncData>);
|
const [syncData, syncError] = await awaiter(
|
||||||
console.log(syncData, syncError);
|
invoke('fansly_sync', {
|
||||||
|
auto
|
||||||
|
}) as Promise<SyncData>
|
||||||
|
);
|
||||||
|
|
||||||
if (syncError || syncData === null) {
|
if (syncError || syncData === null) {
|
||||||
error(
|
error(
|
||||||
@ -93,6 +171,13 @@
|
|||||||
syncState.syncing = false;
|
syncState.syncing = false;
|
||||||
syncState.error = true;
|
syncState.error = true;
|
||||||
syncState.message = syncError ?? 'Sync data was null';
|
syncState.message = syncError ?? 'Sync data was null';
|
||||||
|
|
||||||
|
// Send failure notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Sync Failed!',
|
||||||
|
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||||
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +195,12 @@
|
|||||||
syncState.syncing = false;
|
syncState.syncing = false;
|
||||||
syncState.error = true;
|
syncState.error = true;
|
||||||
syncState.message = saveConfigError ?? 'Save config data was null';
|
syncState.message = saveConfigError ?? 'Save config data was null';
|
||||||
|
|
||||||
|
// Send failure notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Sync Failed!',
|
||||||
|
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +218,7 @@
|
|||||||
soundName = 'completion-sucess';
|
soundName = 'completion-sucess';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!auto)
|
||||||
await sendNotification({
|
await sendNotification({
|
||||||
title: 'FanslySync: Sync Successful!',
|
title: 'FanslySync: Sync Successful!',
|
||||||
body: 'Data synced successfully. Please look at the app for more details.',
|
body: 'Data synced successfully. Please look at the app for more details.',
|
||||||
@ -134,6 +226,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
info(`[FanslySync::syncNow] Manual sync completed successfully.`);
|
info(`[FanslySync::syncNow] Manual sync completed successfully.`);
|
||||||
|
|
||||||
|
if (auto) return syncData;
|
||||||
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doUpdate() {
|
async function doUpdate() {
|
||||||
@ -162,13 +257,357 @@
|
|||||||
console.log('User declined update');
|
console.log('User declined update');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function enableAutoSync() {
|
||||||
|
const isAutoStartEnabled = await isEnabled();
|
||||||
|
|
||||||
|
if (!isAutoStartEnabled) {
|
||||||
|
// Required to enable autosync. Ask user for permission
|
||||||
|
const confirm = await ask(
|
||||||
|
`We've detected that FanslySync is not set to start automatically with the system. To enable Auto Sync, we need to enable this feature. Would you like to enable this feature now?`,
|
||||||
|
{
|
||||||
|
title: 'FanslySync | Enable Auto Start',
|
||||||
|
okLabel: 'Yes',
|
||||||
|
cancelLabel: 'No',
|
||||||
|
kind: 'warning'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
// Error out
|
||||||
|
await message(
|
||||||
|
`Auto Sync cannot be enabled without enabling the Auto Start feature. Please enable the Auto Start feature and try again.`,
|
||||||
|
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
await toast.promise(enable(), {
|
||||||
|
loading: 'Enabling Auto Start...',
|
||||||
|
success: 'Auto Start enabled successfully.',
|
||||||
|
error: 'Failed to enable Auto Start. Please try again.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure they have a sync token set
|
||||||
|
if (!config?.sync_token || config?.sync_token.length === 0) {
|
||||||
|
await message(
|
||||||
|
`Auto Sync cannot be enabled without a valid sync token. Please set a sync token in settings and try again.`,
|
||||||
|
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable autosync
|
||||||
|
config!.auto_sync_enabled = !config?.auto_sync_enabled;
|
||||||
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
|
||||||
|
if (saveConfigError) {
|
||||||
|
await message(
|
||||||
|
`Failed to save Auto Sync configuration. Please try again. Error: ${saveConfigError}`,
|
||||||
|
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||||
|
);
|
||||||
|
error(
|
||||||
|
`[FanslySync::enableAutoSync] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear interval if autosync is disabled, set if enabled
|
||||||
|
if (config?.auto_sync_enabled) {
|
||||||
|
syncInterval = setInterval(
|
||||||
|
async () => {
|
||||||
|
if (config?.auto_sync_enabled) {
|
||||||
|
info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
||||||
|
const nextIntervalTime = new Date(
|
||||||
|
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
|
);
|
||||||
|
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
||||||
|
const returnedData = await syncNow(true);
|
||||||
|
if (!returnedData || returnedData === null) {
|
||||||
|
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||||
|
|
||||||
|
// Send error notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
|
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
info(
|
||||||
|
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||||
|
);
|
||||||
|
|
||||||
|
const [_, uploadErr] = await awaiter(
|
||||||
|
invoke('fansly_upload_auto_sync_data', {
|
||||||
|
token: config?.sync_token,
|
||||||
|
data: returnedData
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (uploadErr) {
|
||||||
|
error(
|
||||||
|
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Send error notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Failed!',
|
||||||
|
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send success notification
|
||||||
|
await sendNotification({
|
||||||
|
title: 'FanslySync: Auto Sync Successful!',
|
||||||
|
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||||
|
);
|
||||||
|
|
||||||
|
// Run a auto sync as soon as it's enabled
|
||||||
|
const returnedData = await syncNow(true);
|
||||||
|
if (!returnedData || returnedData === null) {
|
||||||
|
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||||
|
// Disable autosync, resave, and error out on the UI
|
||||||
|
config!.auto_sync_enabled = false;
|
||||||
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
|
||||||
|
if (saveConfigError)
|
||||||
|
toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.error(
|
||||||
|
'Self test of Auto Sync failed (SYNC_ERR). Please check the logs for more details.',
|
||||||
|
{
|
||||||
|
duration: 5000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
info(
|
||||||
|
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||||
|
);
|
||||||
|
|
||||||
|
const [_, uploadErr] = await awaiter(
|
||||||
|
invoke('fansly_upload_auto_sync_data', {
|
||||||
|
token: config?.sync_token,
|
||||||
|
data: returnedData
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (uploadErr) {
|
||||||
|
error(
|
||||||
|
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Disable autosync, resave, and error out on the UI
|
||||||
|
config!.auto_sync_enabled = false;
|
||||||
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
if (saveConfigError)
|
||||||
|
toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.error(
|
||||||
|
'Self test of Auto Sync failed (UPLOAD_ERR). Please check the logs for more details.',
|
||||||
|
{
|
||||||
|
duration: 5000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (syncInterval) {
|
||||||
|
clearInterval(syncInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info(`[FanslySync::enableAutoSync] Auto Sync configuration saved successfully.`);
|
||||||
|
const nextInterval = new Date(Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000);
|
||||||
|
const nextIntervalString = nextInterval.toLocaleTimeString();
|
||||||
|
|
||||||
|
toast.success(
|
||||||
|
`${
|
||||||
|
config?.auto_sync_enabled ? 'Enabled' : 'Disabled'
|
||||||
|
} Auto Sync successfully. ${config?.auto_sync_enabled ? `The next sync will occur at ${nextIntervalString}.` : ''}`,
|
||||||
|
{
|
||||||
|
duration: 5000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSyncTokenEntered() {
|
||||||
|
// Check if the sync token is valid
|
||||||
|
autoSyncConfigState.validatingToken = true;
|
||||||
|
|
||||||
|
const [_, tokenError] = await awaiter(
|
||||||
|
invoke('fansly_check_sync_token', { token: autoSyncConfig.syncToken })
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tokenError) {
|
||||||
|
error(`[FanslySync::onSyncTokenEntered] Failed to validate sync token. Error: ${tokenError}`);
|
||||||
|
autoSyncConfigState.validatingToken = false;
|
||||||
|
autoSyncConfigState.tokenValid = false;
|
||||||
|
canSave = false;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
info(`[FanslySync::onSyncTokenEntered] Sync token validated successfully.`);
|
||||||
|
autoSyncConfigState.validatingToken = false;
|
||||||
|
autoSyncConfigState.tokenValid = true;
|
||||||
|
canSave = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onAutoSyncSave() {
|
||||||
|
// Close the modal
|
||||||
|
isAutoSyncConfigModalOpen = false;
|
||||||
|
|
||||||
|
const savingToast = await toast.loading('Saving Auto Sync configuration...');
|
||||||
|
|
||||||
|
config!.sync_interval = autoSyncConfig.interval;
|
||||||
|
config!.sync_token = autoSyncConfig.syncToken;
|
||||||
|
|
||||||
|
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||||
|
|
||||||
|
if (saveConfigError) {
|
||||||
|
await toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||||
|
id: savingToast
|
||||||
|
});
|
||||||
|
error(
|
||||||
|
`[FanslySync::onAutoSyncSave] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
info(`[FanslySync::onAutoSyncSave] Auto Sync configuration saved successfully.`);
|
||||||
|
await toast.success('Auto Sync configuration saved successfully.', { id: savingToast });
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container bg-zinc-800 w-screen h-screen">
|
<div class="container bg-zinc-800 w-screen h-screen">
|
||||||
<!-- Top header, Bambu Connect at the left side, settings icon on the right -->
|
<!-- Create config modal -->
|
||||||
|
{#if isAutoSyncConfigModalOpen}
|
||||||
|
<div
|
||||||
|
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-10"
|
||||||
|
transition:fade={{ duration: 300 }}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="bg-zinc-900 p-4 rounded-lg"
|
||||||
|
in:fly={{ y: 20, duration: 300 }}
|
||||||
|
out:fly={{ y: 20, duration: 200 }}
|
||||||
|
>
|
||||||
|
<h1 class="text-2xl font-bold text-gray-200">Auto Sync Configuration</h1>
|
||||||
|
<p class="text-gray-400 mt-1">
|
||||||
|
Configure the Auto Sync feature here. Please ensure you have a valid sync token set in
|
||||||
|
settings.
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-col mt-2">
|
||||||
|
<label for="syncInterval" class="text-gray-200">Sync Interval (in hours)</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id="syncInterval"
|
||||||
|
class="bg-zinc-700 text-gray-200 p-2 rounded-lg mt-1"
|
||||||
|
placeholder="Enter sync interval in hours"
|
||||||
|
bind:value={autoSyncConfig.interval}
|
||||||
|
min="1"
|
||||||
|
/>
|
||||||
|
<p class="text-gray-400 mt-1">
|
||||||
|
How often should the app sync data automatically? Please enter a number in hours. The
|
||||||
|
minimum value is 1 hour.
|
||||||
|
</p>
|
||||||
|
<label for="syncToken" class="text-gray-200 mt-2">Sync Token</label>
|
||||||
|
<div class="relative flex items-center">
|
||||||
|
<!-- Sync token input. Check in the input for valid token, x not, question mark empty -->
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="syncToken"
|
||||||
|
class="bg-zinc-700 text-gray-200 p-2 rounded-lg mt-1 w-full pr-10"
|
||||||
|
placeholder="Enter sync token"
|
||||||
|
bind:value={autoSyncConfig.syncToken}
|
||||||
|
on:change={onSyncTokenEntered}
|
||||||
|
/>
|
||||||
|
{#if !autoSyncConfigState.validatingToken && autoSyncConfigState.tokenValid}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="absolute right-2 bottom-2 w-6 h-6 text-green-500"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
{:else if !autoSyncConfigState.validatingToken && !autoSyncConfigState.tokenValid}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="absolute right-2 bottom-2 w-6 h-6 text-red-500"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
{:else if autoSyncConfigState.validatingToken}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="absolute right-2 bottom-2 w-6 h-6 text-gray-400 animate-spin"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-400 mt-1">
|
||||||
|
Unfocus (click out of) the input to validate the token. A green checkmark means the
|
||||||
|
token is valid.
|
||||||
|
</p>
|
||||||
|
<div class="flex mt-2">
|
||||||
|
<button
|
||||||
|
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-all duration-200 ease-in-out"
|
||||||
|
disabled={!canSave}
|
||||||
|
on:click={onAutoSyncSave}
|
||||||
|
>
|
||||||
|
{canSave ? 'Save' : 'Please enter a valid sync token'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="bg-red-500 text-white px-4 py-2 rounded-lg w-full ml-2 disabled:opacity-50 disabled:cursor-not-allowed hover:bg-red-600 transition-all duration-200 ease-in-out"
|
||||||
|
on:click={() => {
|
||||||
|
isAutoSyncConfigModalOpen = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- Top header, FanslySync at the left side, settings icon on the right -->
|
||||||
<div class="flex justify-between items-center h-16 px-4 bg-zinc-900">
|
<div class="flex justify-between items-center h-16 px-4 bg-zinc-900">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img src="/fanslySync.png" alt="FanslySynct" class="w-8 h-8" />
|
<img src="/fanslySync.png" alt="FanslySync" class="w-8 h-8" />
|
||||||
<h1 class="text-2xl font-bold text-gray-200 ml-2">FanslySync</h1>
|
<h1 class="text-2xl font-bold text-gray-200 ml-2">FanslySync</h1>
|
||||||
<span class="text-gray-400 ml-2"
|
<span class="text-gray-400 ml-2"
|
||||||
>v{versionData.appVersion} (runtime: {versionData.tauriVersion})</span
|
>v{versionData.appVersion} (runtime: {versionData.tauriVersion})</span
|
||||||
@ -240,40 +679,54 @@
|
|||||||
<!-- Automatic sync card -->
|
<!-- Automatic sync card -->
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="bg-zinc-700 p-4 rounded-lg">
|
<div class="bg-zinc-700 p-4 rounded-lg">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
<h1 class="text-xl font-bold text-gray-200">Automatic Sync</h1>
|
<h1 class="text-xl font-bold text-gray-200">Automatic Sync</h1>
|
||||||
|
<!-- Status badge -->
|
||||||
|
<span
|
||||||
|
class={`px-2 py-1 rounded-lg text-xs font-bold ${
|
||||||
|
config?.auto_sync_enabled ? 'bg-green-500' : 'bg-red-500'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{config?.auto_sync_enabled ? 'Enabled' : 'Disabled'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<p class="text-gray-400 mt-1">
|
<p class="text-gray-400 mt-1">
|
||||||
Sync content automatically every {config?.sync_interval} hours. Please ensure you have
|
Sync content automatically every {config?.sync_interval}
|
||||||
a stable internet connection.
|
{(config?.sync_interval ?? 0 > 1) ? 'hour' : 'hours'}. Please ensure you have a
|
||||||
|
stable internet connection.
|
||||||
</p>
|
</p>
|
||||||
<div class="flex mt-2">
|
<div class="flex mt-2">
|
||||||
<button
|
<button
|
||||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full"
|
class={` text-white px-4 py-2 rounded-lg w-full ${
|
||||||
on:click={() => console.log('Automatic sync clicked')}
|
!config?.auto_sync_enabled
|
||||||
|
? 'bg-green-500 hover:bg-green-600'
|
||||||
|
: 'bg-red-500 hover:bg-red-600'
|
||||||
|
} disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 ease-in-out`}
|
||||||
|
on:click={enableAutoSync}
|
||||||
|
disabled={syncState.syncing}
|
||||||
>
|
>
|
||||||
Enable
|
{syncState.syncing
|
||||||
|
? 'Sync in progress. Please wait.'
|
||||||
|
: config?.auto_sync_enabled
|
||||||
|
? 'Disable'
|
||||||
|
: 'Enable'}
|
||||||
|
{!syncState.syncing ? 'Auto Sync' : ''}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full ml-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 ease-in-out hover:bg-blue-700"
|
||||||
|
on:click={() => {
|
||||||
|
isAutoSyncConfigModalOpen = true;
|
||||||
|
}}
|
||||||
|
disabled={config?.auto_sync_enabled || syncState.syncing}
|
||||||
|
>
|
||||||
|
{syncState.syncing
|
||||||
|
? 'Sync in progress. Please wait.'
|
||||||
|
: config?.auto_sync_enabled
|
||||||
|
? 'Disable Auto Sync To Edit'
|
||||||
|
: 'Edit Auto Sync Configuration'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="absolute top-0 left-0 right-0 bottom-0 bg-white/30 backdrop-blur-sm flex flex-col justify-center items-center rounded-lg"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
class="size-10 text-blue-400"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<h1 class="text-xl font-bold text-gray-200 ml-2">Automatic Sync is coming soon!</h1>
|
|
||||||
<p class="text-white mt-1">Stay tuned for updates.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Manual sync card -->
|
<!-- Manual sync card -->
|
||||||
@ -285,7 +738,9 @@
|
|||||||
<div class="flex mt-2">
|
<div class="flex mt-2">
|
||||||
<button
|
<button
|
||||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-all duration-200 ease-in-out"
|
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-all duration-200 ease-in-out"
|
||||||
on:click={syncNow}
|
on:click={() => {
|
||||||
|
syncNow(false);
|
||||||
|
}}
|
||||||
disabled={syncState.syncing}
|
disabled={syncState.syncing}
|
||||||
>
|
>
|
||||||
{syncState.syncing ? 'Syncing...' : 'Sync Now'}
|
{syncState.syncing ? 'Syncing...' : 'Sync Now'}
|
||||||
|
2
src/routes/home/debug.log
Normal file
2
src/routes/home/debug.log
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[0813/143825.367:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||||
|
[0813/143918.868:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
Loading…
x
Reference in New Issue
Block a user