diff --git a/client/config.xml b/client/config.xml index c48e640..764b47b 100644 --- a/client/config.xml +++ b/client/config.xml @@ -1,5 +1,5 @@ - + Reis Can @@ -20,4 +20,4 @@ TizenBrewService - \ No newline at end of file + diff --git a/client/package.json b/client/package.json index 661c050..db4a776 100644 --- a/client/package.json +++ b/client/package.json @@ -7,11 +7,11 @@ "services/tizenbrew-installer-service/dist/**" ], "targets": [ - "node20-linux-x64", - "node20-win-x64", - "node20-macos-arm64", - "node20-macos-x64", - "node20-linux-arm64" + "node22-linux-x64", + "node22-win-x64", + "node22-macos-arm64", + "node22-macos-x64", + "node22-linux-arm64" ], "outputPath": "dist" } diff --git a/client/services/tizenbrew-installer-service/index.js b/client/services/tizenbrew-installer-service/index.js index 49801c4..a09135b 100644 --- a/client/services/tizenbrew-installer-service/index.js +++ b/client/services/tizenbrew-installer-service/index.js @@ -1,6 +1,12 @@ "use strict"; const isTV = typeof tizen !== 'undefined'; +// Required due to svdca.samsungqbe.com certificate expiring and Samsung not doing anything. +// Also for older Tizen TVs who had their root certificate break. +process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + +// To remove the DeprecationWarning displayed. +process.removeAllListeners('warning'); module.exports.onStart = function () { console.log('Service started'); @@ -38,6 +44,13 @@ module.exports.onStart = function () { app.use(express.static(`${process.platform === 'win32' ? 'C:\\' : '/'}snapshot/client`)); } else app.use(express.static(join(__dirname, '../../'))); } + + app.get('/ui/dist/index.html/desktop', (_, res) => { + if (existsSync(`${process.platform === 'win32' ? 'C:\\' : '/'}snapshot/client`)) { + res.sendFile(`${process.platform === 'win32' ? 'C:\\' : '/'}snapshot/client/ui/dist/index.html`); + } else res.sendFile((join(__dirname, '../../ui/dist/index.html'))); + }); + let isTizen7OrHigher = isTV && Number(tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version').split('.')[0]) >= 7; const isTizen3 = isTV && tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version').startsWith('3.0'); const wsServer = new WebSocket.Server({ server: app.listen(8091) }); @@ -125,78 +138,116 @@ module.exports.onStart = function () { return wsConn.send(wsConn.Event(Events.Error, `Invalid JSON: ${message}`)); } - const { type, payload } = msg; + function parseAndInstall(buffer) { + parsePackage(buffer) + .then(pkg => { + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installing')); + if (isTV) { + if (!existsSync('/home/owner/share/tmp/sdk_tools')) mkdirRecursive(`/home/owner/share/tmp/sdk_tools`); + writeFileSync(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, buffer); + } else { + PushFile(adbClient, `/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, buffer, () => { + installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId, adbClient) + .then(result => { + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); + wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); + }); + }); + return; + } - switch (type) { - case Events.InstallPackage: { - if (!isTizen3 && isTV) { - if (canConnectToDevice !== null && !canConnectToDevice) { - return wsConn.send(wsConn.Event(Events.Error, 'errors.debuggingNotEnabled')); - } else if (canConnectToDevice === null) return; - } - if (isTizen7OrHigher) { - // Check if we have author and distributor certificates - const config = readConfig(); - if (!config.authorCert || !config.distributorCert || !config.password) { - return wsConn.send(wsConn.Event(Events.InstallPackage, { response: 2 })); + if (payload.url && payload.url === 'reisxd/TizenBrewInstaller' && + !isTV && existsSync(`${homedir()}/share/tizenbrewInstallerConfig.json`)) { + // Send the existing config to the TV + PushFile(adbClient, '/home/owner/share/tizenbrewInstallerConfig.json', readFileSync(`${homedir()}/share/tizenbrewInstallerConfig.json`), () => { + console.log('Config pushed to TV for Installer'); + }); } - } - function parseAndInstall(buffer) { - parsePackage(buffer) - .then(pkg => { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installing')); - if (isTV) { - if (!existsSync('/home/owner/share/tmp/sdk_tools')) mkdirRecursive(`/home/owner/share/tmp/sdk_tools`); - writeFileSync(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, buffer); - } else { - PushFile(adbClient, `/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, buffer, () => { - installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId, adbClient) - .then(result => { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); - wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); - }); - }); - return; - } - - if (payload.url && payload.url === 'reisxd/TizenBrewInstaller' && - !isTV && existsSync(`${homedir()}/share/tizenbrewInstallerConfig.json`)) { - // Send the existing config to the TV - PushFile(adbClient, '/home/owner/share/tizenbrewInstallerConfig.json', readFileSync(`${homedir()}/share/tizenbrewInstallerConfig.json`), () => { - console.log('Config pushed to TV for Installer'); - }); - } - - if (isTizen3 && isTV) { - const result = installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId); - setValue('db/sdk/develop/ip', 'string', '127.0.0.1'); - setValue('db/sdk/develop/mode', 'int32', '1'); - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); - wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); - } else if (isTV) { - createAdbConnection() - .then(adbClient => { - installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId, adbClient) - .then(result => { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); - wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); - setTimeout(() => { - adbClient._stream.end(); - adbClient._stream.destroy(); - }, 5000); - }); - }) - .catch(err => { - wsConn.send(wsConn.Event(Events.Error, err.message.includes('.') ? err.message : `Error creating ADB connection: ${err.message}`)); + if (isTizen3 && isTV) { + const result = installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId); + setValue('db/sdk/develop/ip', 'string', '127.0.0.1'); + setValue('db/sdk/develop/mode', 'int32', '1'); + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); + wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); + } else if (isTV) { + createAdbConnection() + .then(adbClient => { + installPackage(`/home/owner/share/tmp/sdk_tools/package.${pkg.isWgt ? 'wgt' : 'tpk'}`, pkg.packageId, adbClient) + .then(result => { + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.installed')); + wsConn.send(wsConn.Event(Events.InstallPackage, { response: 0, result })); + setTimeout(() => { + adbClient._stream.end(); + adbClient._stream.destroy(); + }, 5000); }); - } - }) - .catch(err => { - wsConn.send(wsConn.Event(Events.Error, `Error parsing package: ${err.message}`)); - console.error(err); - }); + }) + .catch(err => { + wsConn.send(wsConn.Event(Events.Error, err.message.includes('.') ? err.message : `Error creating ADB connection: ${err.message}`)); + }); + } + }) + .catch(err => { + wsConn.send(wsConn.Event(Events.Error, `Error parsing package: ${err.message}`)); + console.error(err); + }); + } + + function resignOrInstall(buffer) { + if (isTizen7OrHigher) { + const config = readConfig(); + const certificates = { + authorCert: Buffer.from(config.authorCert, 'base64').toString('binary'), + distributorCert: Buffer.from(config.distributorCert, 'base64').toString('binary'), + password: config.password + }; + + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.resigning')); + resignPackage(certificates, buffer) + .then(resignedBuffer => { + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.parsing')); + parseAndInstall(resignedBuffer); + }) + .catch(err => { + wsConn.send(wsConn.Event(Events.Error, `Error resigning package: ${err.message}`)); + }); + } else { + wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.parsing')); + parseAndInstall(buffer); + } + } + + function checkPrecondition() { + if (!isTizen3 && isTV) { + if (canConnectToDevice !== null && !canConnectToDevice) { + wsConn.send(wsConn.Event(Events.Error, 'errors.debuggingNotEnabled')); + return false; + } else if (canConnectToDevice === null) return false; + } + if (isTizen7OrHigher) { + // Check if we have author and distributor certificates + const config = readConfig(); + if (!config.authorCert || !config.distributorCert || !config.password) { + wsConn.send(wsConn.Event(Events.InstallPackage, { response: 2 })); + return false; } + } + + if (!isTV && (!adbClient || !isConnected)) { + // Somethings wrong. + wsConn.send(wsConn.Event(Events.ConnectToTV, { success: false })) + return false; + } + + return true; + } + + const { type, payload } = msg; + + switch (type) { + case Events.InstallPackage: { + if (!checkPrecondition()) return; if (payload.url.split('/').length === 2) { // GitHub repository @@ -207,24 +258,7 @@ module.exports.onStart = function () { fetch(asset.browser_download_url) .then(res => res.buffer()) .then(buffer => { - if (isTizen7OrHigher) { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.resigning')); - const config = readConfig(); - const certificates = { - authorCert: Buffer.from(config.authorCert, 'base64').toString('binary'), - distributorCert: Buffer.from(config.distributorCert, 'base64').toString('binary'), - password: config.password - }; - - resignPackage(certificates, buffer) - .then(resignedBuffer => { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.parsing')); - parseAndInstall(resignedBuffer); - }) - .catch(err => { - wsConn.send(wsConn.Event(Events.Error, `Error resigning package: ${err.message}`)); - }); - } else parseAndInstall(buffer); + resignOrInstall(buffer) }) .catch(err => { wsConn.send(wsConn.Event(Events.Error, `Error fetching release asset: ${err.message}`)); @@ -235,27 +269,7 @@ module.exports.onStart = function () { } else { // USB installation const fileBuffer = readFileSync(payload.url); - if (isTizen7OrHigher) { - const config = readConfig(); - const certificates = { - authorCert: Buffer.from(config.authorCert, 'base64').toString('binary'), - distributorCert: Buffer.from(config.distributorCert, 'base64').toString('binary'), - password: config.password - }; - - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.resigning')); - resignPackage(certificates, fileBuffer) - .then(resignedBuffer => { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.parsing')); - parseAndInstall(resignedBuffer); - }) - .catch(err => { - wsConn.send(wsConn.Event(Events.Error, `Error resigning package: ${err.message}`)); - }); - } else { - wsConn.send(wsConn.Event(Events.InstallationStatus, 'installStatus.parsing')); - parseAndInstall(fileBuffer); - } + resignOrInstall(fileBuffer); } break; @@ -282,6 +296,11 @@ module.exports.onStart = function () { wsConn.send(wsConn.Event(Events.NavigateDirectory, metadata)); break; } + case Events.InstallFile: { + if (!checkPrecondition()) return; + const fileBuffer = Buffer.from(payload, 'base64'); + resignOrInstall(fileBuffer); + } case Events.DeleteConfiguration: { const config = readConfig(); config.authorCert = null; @@ -342,7 +361,7 @@ module.exports.onStart = function () { privilegeLevel: 'Partner' }; - function createCert(adbClient) { + function createCert() { createSamsungCertificate(authorInfo, accessInfo, adbClient, isTV) .then(certificate => { const currentConfig = readConfig(); @@ -371,12 +390,15 @@ module.exports.onStart = function () { if (isTV) { if (!adbClient && !isConnected) { createAdbConnection().then(adbClient => { - createCert(adbClient); + createCert(); }).catch(err => { response.status(500).json({ error: err.message }); }); - } else createCert(adbClient); - } else createCert(adbClient); + } else createCert(); + } else if (!adbClient || !isConnected) { + response.send('Connection between the TV and the device was broken. Please reconnect to your TV from the previous page and try again.'); + if (wsClient) wsClient.send(wsClient.Event(Events.ConnectToTV, { success: false })) + } else createCert(); } else { response.send(AccessInfoHTMLPage); } diff --git a/client/services/tizenbrew-installer-service/utils/wsCommunication.js b/client/services/tizenbrew-installer-service/utils/wsCommunication.js index 50febfb..d533e3c 100644 --- a/client/services/tizenbrew-installer-service/utils/wsCommunication.js +++ b/client/services/tizenbrew-installer-service/utils/wsCommunication.js @@ -22,7 +22,8 @@ const Events = { Error: 3, InstallationStatus: 4, DeleteConfiguration: 5, - ConnectToTV: 6 + ConnectToTV: 6, + InstallFile: 7 }; module.exports = { diff --git a/client/ui/src/components/ClientContext.jsx b/client/ui/src/components/ClientContext.jsx index 6cde4a3..7d423a9 100644 --- a/client/ui/src/components/ClientContext.jsx +++ b/client/ui/src/components/ClientContext.jsx @@ -3,6 +3,7 @@ import { useReducer } from 'preact/hooks'; const initialState = { sharedData: { + tizenBrewRepo: localStorage.getItem('tizenBrewRepo') || 'reisxd/TizenBrew', state: null, directory: [], error: { @@ -32,6 +33,9 @@ function reducer(state, action) { return { ...state, sharedData: { ...state.sharedData, qrCodeShow: action.payload } }; case 'SET_CONNECTED_TO_TV': return { ...state, sharedData: { ...state.sharedData, connectedToTV: action.payload } }; + case 'SET_TIZENBREW_REPO': + localStorage.setItem('tizenBrewRepo', action.payload); + return { ...state, sharedData: { ...state.sharedData, tizenBrewRepo: action.payload } }; default: return state; } diff --git a/client/ui/src/components/WebSocketClient.js b/client/ui/src/components/WebSocketClient.js index cc0c323..5c5e1ce 100644 --- a/client/ui/src/components/WebSocketClient.js +++ b/client/ui/src/components/WebSocketClient.js @@ -6,7 +6,8 @@ const Events = { Error: 3, InstallationStatus: 4, DeleteConfiguration: 5, - ConnectToTV: 6 + ConnectToTV: 6, + InstallFile: 7 }; class Client { diff --git a/client/ui/src/components/i18nResources.js b/client/ui/src/components/i18nResources.js index 69d81d7..4406aa6 100644 --- a/client/ui/src/components/i18nResources.js +++ b/client/ui/src/components/i18nResources.js @@ -3,12 +3,16 @@ import FrenchLanguage from '../lang/fr.json'; import SerbianLanguage from '../lang/sr.json'; import TurkishLanguage from '../lang/tr.json'; import VietnameseLanguage from '../lang/vi.json'; -import DutchLanguage from '../lang/nl.json'; +import DutchLanguage from '../lang/nl.json'; +import GermanLanguage from '../lang/de.json'; const resources = { en: { translation: EnglishLanguage }, + de: { + translation: GermanLanguage + }, fr: { translation: FrenchLanguage }, diff --git a/client/ui/src/lang/de.json b/client/ui/src/lang/de.json new file mode 100644 index 0000000..2b361c7 --- /dev/null +++ b/client/ui/src/lang/de.json @@ -0,0 +1,43 @@ +{ + "service": { + "alreadyRunning": "Der Dienst läuft bereits.", + "started": "Dienst gestartet." + }, + "errors": { + "debuggingNotEnabled": "Fehler: Verbindung zum SDB-Daemon konnte nicht hergestellt werden. Hast du die Host-PC-IP wirklich auf 127.0.0.1 geändert? Falls ja, halte den Einschaltknopf gedrückt, bis das Samsung-Logo erscheint." + }, + "installStatus": { + "fetching": "Paket wird abgerufen", + "resigning": "Paket wird neu signiert", + "parsing": "Paket wird verarbeitet", + "installing": "Paket wird installiert", + "installed": "Paket installiert", + "installFailed": "Installation fehlgeschlagen: {{line}}" + }, + "resigning": { + "resigningRequired": "Neu-Signierung erforderlich", + "resigningRequiredDesc": "Seit Tizen 7 müssen alle Pakete mit einem Samsung-Zertifikat neu signiert werden.\nBitte scanne den QR-Code, um dich bei deinem Samsung-Konto anzumelden, und kopiere anschließend die JSON-Antwort, die du nach der Anmeldung erhältst.", + "resigningRequiredPCDesc": "Seit Tizen 7 müssen alle Pakete mit einem Samsung-Zertifikat neu signiert werden.\nBitte klicke auf die Schaltfläche unten, um dich bei deinem Samsung-Konto anzumelden.", + "resigningRequiredOpenAuthButton": "Bei Samsung-Konto anmelden", + "resigningRequiredAccessInfo": "Nachdem du die JSON-Antwort kopiert hast, gehe zu http://{{ip}}:4794, füge sie in das Eingabefeld ein und drücke die Schaltfläche \"Submit\".", + "resigningDeviceSameNetwork": "Stelle sicher, dass sich dein Gerät im selben Netzwerk wie dein Fernseher befindet." + }, + "installer": { + "installTB": "TizenBrew installieren", + "installTBI": "TizenBrew Installer installieren", + "connectToTV": "Mit Fernseher verbinden", + "updateTB": "TizenBrew aktualisieren", + "installFromUSB": "Von USB installieren", + "installFromGH": "Von GitHub installieren", + "selectToInstall": "Datei zur Installation auswählen", + "installingAgain": "TizenBrew Installer ist als USB-Demopaket installiert. Es wird jetzt als normales Paket neu installiert.", + "alreadyInstalled": "TizenBrew Installer ist als USB-Demopaket installiert. Du kannst es jetzt deinstallieren." + }, + "installerDesktop": { + "sdbConnectionRefused": "Verbindung zum SDB-Daemon konnte nicht hergestellt werden. Stelle sicher, dass der Fernseher eingeschaltet ist und die IP korrekt ist.", + "sdbConnectionReset": "Verbindung zum SDB-Daemon konnte nicht hergestellt werden. Entweder wurde die Host-PC-IP nicht auf die IP dieses Geräts gesetzt, oder der Fernseher wurde nicht richtig neu gestartet. Halte den Einschaltknopf gedrückt, bis das Samsung-Logo erscheint, um den Fernseher neu zu starten." + }, + "__contributors": [ + "KrX3D" + ] +} diff --git a/client/ui/src/lang/en.json b/client/ui/src/lang/en.json index 72bfceb..7042f45 100644 --- a/client/ui/src/lang/en.json +++ b/client/ui/src/lang/en.json @@ -29,6 +29,7 @@ "updateTB": "Update TizenBrew", "installFromUSB": "Install from USB", "installFromGH": "Install from GitHub", + "selectToInstall": "Select file to install", "installingAgain": "TizenBrew Installer is installed as an USB Demo Package. It will now be reinstalled as a normal package.", "alreadyInstalled": "TizenBrew Installer as an USB Demo Package is installed. You can now uninstall it." }, diff --git a/client/ui/src/lang/fr.json b/client/ui/src/lang/fr.json index fd30029..55bb47d 100644 --- a/client/ui/src/lang/fr.json +++ b/client/ui/src/lang/fr.json @@ -25,6 +25,7 @@ "updateTB": "Mettre à jour TizenBrew", "installFromUSB": "Installer à partir d'un périphérique USB", "installFromGH": "Installer depuis GitHub", + "selectToInstall": "Sélectionner un fichier à installer", "installingAgain": "TizenBrew Installer est installé en tant que Paquet Démo USB. Il va maintenant être réinstallé en tant que paquet normal.", "alreadyInstalled": "Le Paquet Démo USB de TizenBrew Installer est installé. Vous pouvez maintenant le supprimer." }, diff --git a/client/ui/src/lang/nl.json b/client/ui/src/lang/nl.json index fe1d5d9..b4a7172 100644 --- a/client/ui/src/lang/nl.json +++ b/client/ui/src/lang/nl.json @@ -25,6 +25,7 @@ "updateTB": "TizenBrew updaten", "installFromUSB": "Installeren van USB", "installFromGH": "Installeren van GitHub", + "selectToInstall": "Selecteer bestand om te installeren", "installingAgain": "TizenBrew Installer is geinstalleerd als een USB Demo Package. Het zal nu worden geinstalleerd als een normaal pakket.", "alreadyInstalled": "TizenBrew Installer als een USB Demo Package is geinstalleerd. U kunt het nu verwijderen." }, diff --git a/client/ui/src/lang/sr.json b/client/ui/src/lang/sr.json index 7ffc2af..8a22bb4 100644 --- a/client/ui/src/lang/sr.json +++ b/client/ui/src/lang/sr.json @@ -25,6 +25,7 @@ "updateTB": "Ажурирање TizenBrew", "installFromUSB": "Инсталација са USB флешке", "installFromGH": "Инсталација са GitHub-а", + "selectToInstall": "Изабери фајл за инсталацију", "installingAgain": "TizenBrew Installer је инсталиран као USB Demo пакет. Сада ће бити поново инсталиран као обичан пакет.", "alreadyInstalled": "TizenBrew Installer као USB Demo пакет је инсталиран. Сада га можете деинсталирати." }, diff --git a/client/ui/src/lang/tr.json b/client/ui/src/lang/tr.json index b22b447..01afc1c 100644 --- a/client/ui/src/lang/tr.json +++ b/client/ui/src/lang/tr.json @@ -29,6 +29,7 @@ "updateTB": "TizenBrew'ı Güncelle", "installFromUSB": "USB'den Kur", "installFromGH": "GitHub'dan Kur", + "selectToInstall": "Kurmak için dosyas seç", "installingAgain": "TizenBrew Installer, USB Demo paketi olarak yüklüdür. Şimdi normal paket olarak yeniden yüklenecektir.", "alreadyInstalled": "TizenBrew Installer, USB Demo paketi olarak yüklüdür. Şimdi USB Demo paketini kaldırabilirsiniz." }, diff --git a/client/ui/src/lang/vi.json b/client/ui/src/lang/vi.json index ef52916..2742eb4 100644 --- a/client/ui/src/lang/vi.json +++ b/client/ui/src/lang/vi.json @@ -25,6 +25,7 @@ "updateTB": "Cập nhật TizenBrew", "installFromUSB": "Cài đặt app từ USB", "installFromGH": "Cài đặt app từ GitHub", + "selectToInstall": "Chọn file để cài đặt", "installingAgain": "TizenBrew Installer đã được cài đặt dưới dạng USB Demo Package. Bây giờ app sẽ tự cài lại như 1 app bình thường.", "alreadyInstalled": "TizenBrew Installer dưới dạng USB Demo Package đang được cài đặt. Bây giờ bạn có thể gỡ cài đặt gói Demo này." }, diff --git a/client/ui/src/pages/Desktop.jsx b/client/ui/src/pages/Desktop.jsx index 7c60bb7..489d0d5 100644 --- a/client/ui/src/pages/Desktop.jsx +++ b/client/ui/src/pages/Desktop.jsx @@ -23,8 +23,28 @@ export default function Desktop() { } }, [context.state.client, context.state.client?.socket?.readyState]); + function onInputChange(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + const dataUrl = e.target.result; + + const base64Data = dataUrl.split(',')[1]; + + context.state.client.send({ + type: Events.InstallFile, + payload: base64Data + }); + } + + reader.readAsDataURL(file); + } + } + return (
+ {context.state.sharedData.qrCodeShow && (
@@ -48,7 +68,7 @@ export default function Desktop() { context.state.client.send({ type: Events.InstallPackage, payload: { - url: 'reisxd/TizenBrew' + url: context.state.sharedData.tizenBrewRepo } }) }}> @@ -84,6 +104,17 @@ export default function Desktop() { + { + const realFileInput = document.getElementById('realFileInput'); + realFileInput.click(); + }}> +

+ + + {t('installer.selectToInstall')} + +

+
) : ( @@ -100,6 +131,7 @@ export default function Desktop() { className="w-full p-2 rounded-lg bg-gray-800 text-gray-200" onChange={(e) => setIp(e.target.value)} onKeyDown={(e) => { + if (e.keyCode === 37 || e.keyCode === 39) { e.stopPropagation(); return; } if (e.keyCode === 13 || e.keyCode === 65376) { ipInputRef.current.blur(); } diff --git a/client/ui/src/pages/Home.jsx b/client/ui/src/pages/Home.jsx index 3e8774f..3e4d424 100644 --- a/client/ui/src/pages/Home.jsx +++ b/client/ui/src/pages/Home.jsx @@ -19,11 +19,13 @@ export default function Home() { // Check if TizenBrew is already installed. let isTizenBrewInstalled = false; + let installedVersion = null; try { - tizen.application.getAppInfo('xvvl3S1bvH.TizenBrewStandalone'); + const appInfo = tizen.application.getAppInfo('xvvl3S1bvH.TizenBrewStandalone'); isTizenBrewInstalled = true; + installedVersion = appInfo.version; } catch (e) { } - + useEffect(() => { if ( @@ -73,7 +75,7 @@ export default function Home() { context.state.client.send({ type: Events.InstallPackage, payload: { - url: 'reisxd/TizenBrew' + url: context.state.sharedData.tizenBrewRepo } }) }}> @@ -90,6 +92,8 @@ export default function Home() { )} +

Repo: {context.state.sharedData.tizenBrewRepo}

+ {installedVersion &&

Installed: {installedVersion}

}
{ loc.route('/ui/dist/index.html/install-from-usb'); diff --git a/client/ui/src/pages/InstallFromGitHub.jsx b/client/ui/src/pages/InstallFromGitHub.jsx index 935b186..56d0bb9 100644 --- a/client/ui/src/pages/InstallFromGitHub.jsx +++ b/client/ui/src/pages/InstallFromGitHub.jsx @@ -7,9 +7,9 @@ import { Events } from '../components/WebSocketClient.js'; import Item from "../components/Item.jsx"; export default function InstallFromGitHub() { - const [name, setName] = useState(''); + const { state, dispatch } = useContext(GlobalStateContext); + const [name, setName] = useState(state.sharedData.tizenBrewRepo || ''); const loc = useLocation(); - const { state } = useContext(GlobalStateContext); const ref = useRef(null); useEffect(() => { @@ -20,22 +20,28 @@ export default function InstallFromGitHub() {
setName(e.target.value)} onKeyDown={(e) => { + if (e.keyCode === 37 || e.keyCode === 39) { e.stopPropagation(); return; } if (e.keyCode === 13 || e.keyCode === 65376) { ref.current.blur(); } }} - onBlur={(e) => { - if (name) { + onBlur={() => { + const repo = name.trim(); + if (repo) { + dispatch({ + type: 'SET_TIZENBREW_REPO', + payload: repo + }); state.client.send({ type: Events.InstallPackage, payload: { - url: name + url: repo } }); } @@ -43,7 +49,7 @@ export default function InstallFromGitHub() { loc.route('/ui/dist/index.html'); setFocus('sn:focusable-item-1'); }} - placeholder="reisxd/TizenBrew" + placeholder="owner/repo" />