mirror of https://github.com/jetkvm/kvm.git
refactor: simplify version check and downgrade
This commit is contained in:
parent
329ad025bf
commit
1bca0c5e26
|
|
@ -239,10 +239,29 @@ func (s *State) getUpdateStatus(
|
||||||
systemUpdate = ¤tSystemUpdate
|
systemUpdate = ¤tSystemUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = s.doGetUpdateStatus(ctx, params, appUpdate, systemUpdate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.componentUpdateStatuses["app"] = *appUpdate
|
||||||
|
s.componentUpdateStatuses["system"] = *systemUpdate
|
||||||
|
|
||||||
|
return appUpdate, systemUpdate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// doGetUpdateStatus is the internal function that gets the update status
|
||||||
|
// it WON'T change the state of the OTA state
|
||||||
|
func (s *State) doGetUpdateStatus(
|
||||||
|
ctx context.Context,
|
||||||
|
params UpdateParams,
|
||||||
|
appUpdate *componentUpdateStatus,
|
||||||
|
systemUpdate *componentUpdateStatus,
|
||||||
|
) error {
|
||||||
// Get local versions
|
// Get local versions
|
||||||
systemVersionLocal, appVersionLocal, err := s.getLocalVersion()
|
systemVersionLocal, appVersionLocal, err := s.getLocalVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error getting local version: %w", err)
|
return fmt.Errorf("error getting local version: %w", err)
|
||||||
}
|
}
|
||||||
appUpdate.localVersion = appVersionLocal.String()
|
appUpdate.localVersion = appVersionLocal.String()
|
||||||
systemUpdate.localVersion = systemVersionLocal.String()
|
systemUpdate.localVersion = systemVersionLocal.String()
|
||||||
|
|
@ -255,7 +274,7 @@ func (s *State) getUpdateStatus(
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("error checking for updates: %w", err)
|
err = fmt.Errorf("error checking for updates: %w", err)
|
||||||
}
|
}
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
appUpdate.url = remoteMetadata.AppURL
|
appUpdate.url = remoteMetadata.AppURL
|
||||||
appUpdate.hash = remoteMetadata.AppHash
|
appUpdate.hash = remoteMetadata.AppHash
|
||||||
|
|
@ -269,7 +288,7 @@ func (s *State) getUpdateStatus(
|
||||||
systemVersionRemote, err := semver.NewVersion(remoteMetadata.SystemVersion)
|
systemVersionRemote, err := semver.NewVersion(remoteMetadata.SystemVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error parsing remote system version: %w", err)
|
err = fmt.Errorf("error parsing remote system version: %w", err)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
systemUpdate.available = systemVersionRemote.GreaterThan(systemVersionLocal)
|
systemUpdate.available = systemVersionRemote.GreaterThan(systemVersionLocal)
|
||||||
systemUpdate.downgradeAvailable = systemVersionRemote.LessThan(systemVersionLocal)
|
systemUpdate.downgradeAvailable = systemVersionRemote.LessThan(systemVersionLocal)
|
||||||
|
|
@ -277,7 +296,7 @@ func (s *State) getUpdateStatus(
|
||||||
appVersionRemote, err := semver.NewVersion(remoteMetadata.AppVersion)
|
appVersionRemote, err := semver.NewVersion(remoteMetadata.AppVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error parsing remote app version: %w, %s", err, remoteMetadata.AppVersion)
|
err = fmt.Errorf("error parsing remote app version: %w, %s", err, remoteMetadata.AppVersion)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
appUpdate.available = appVersionRemote.GreaterThan(appVersionLocal)
|
appUpdate.available = appVersionRemote.GreaterThan(appVersionLocal)
|
||||||
appUpdate.downgradeAvailable = appVersionRemote.LessThan(appVersionLocal)
|
appUpdate.downgradeAvailable = appVersionRemote.LessThan(appVersionLocal)
|
||||||
|
|
@ -293,18 +312,17 @@ func (s *State) getUpdateStatus(
|
||||||
appUpdate.available = false
|
appUpdate.available = false
|
||||||
}
|
}
|
||||||
|
|
||||||
s.componentUpdateStatuses["app"] = *appUpdate
|
return nil
|
||||||
s.componentUpdateStatuses["system"] = *systemUpdate
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUpdateStatus returns the current update status (for backwards compatibility)
|
// GetUpdateStatus returns the current update status (for backwards compatibility)
|
||||||
func (s *State) GetUpdateStatus(ctx context.Context, params UpdateParams) (*UpdateStatus, error) {
|
func (s *State) GetUpdateStatus(ctx context.Context, params UpdateParams) (*UpdateStatus, error) {
|
||||||
_, _, err := s.getUpdateStatus(ctx, params)
|
appUpdate := &componentUpdateStatus{}
|
||||||
|
systemUpdate := &componentUpdateStatus{}
|
||||||
|
err := s.doGetUpdateStatus(ctx, params, appUpdate, systemUpdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting update status: %w", err)
|
return nil, fmt.Errorf("error getting update status: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.ToUpdateStatus(), nil
|
return toUpdateStatus(appUpdate, systemUpdate, ""), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,18 +156,7 @@ func (s *State) GetTargetVersion(component string) string {
|
||||||
return componentUpdate.targetVersion
|
return componentUpdate.targetVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToUpdateStatus converts the State to the UpdateStatus
|
func toUpdateStatus(appUpdate *componentUpdateStatus, systemUpdate *componentUpdateStatus, error string) *UpdateStatus {
|
||||||
func (s *State) ToUpdateStatus() *UpdateStatus {
|
|
||||||
appUpdate, ok := s.componentUpdateStatuses["app"]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
systemUpdate, ok := s.componentUpdateStatuses["system"]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &UpdateStatus{
|
return &UpdateStatus{
|
||||||
Local: &LocalMetadata{
|
Local: &LocalMetadata{
|
||||||
AppVersion: appUpdate.localVersion,
|
AppVersion: appUpdate.localVersion,
|
||||||
|
|
@ -185,10 +174,25 @@ func (s *State) ToUpdateStatus() *UpdateStatus {
|
||||||
SystemDowngradeAvailable: systemUpdate.downgradeAvailable,
|
SystemDowngradeAvailable: systemUpdate.downgradeAvailable,
|
||||||
AppUpdateAvailable: appUpdate.available,
|
AppUpdateAvailable: appUpdate.available,
|
||||||
AppDowngradeAvailable: appUpdate.downgradeAvailable,
|
AppDowngradeAvailable: appUpdate.downgradeAvailable,
|
||||||
Error: s.error,
|
Error: error,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUpdateStatus converts the State to the UpdateStatus
|
||||||
|
func (s *State) ToUpdateStatus() *UpdateStatus {
|
||||||
|
appUpdate, ok := s.componentUpdateStatuses["app"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
systemUpdate, ok := s.componentUpdateStatuses["system"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return toUpdateStatus(&appUpdate, &systemUpdate, s.error)
|
||||||
|
}
|
||||||
|
|
||||||
// IsUpdatePending returns true if an update is pending
|
// IsUpdatePending returns true if an update is pending
|
||||||
func (s *State) IsUpdatePending() bool {
|
func (s *State) IsUpdatePending() bool {
|
||||||
return s.updating
|
return s.updating
|
||||||
|
|
|
||||||
|
|
@ -1151,9 +1151,10 @@ var rpcHandlers = map[string]RPCHandler{
|
||||||
"setDevChannelState": {Func: rpcSetDevChannelState, Params: []string{"enabled"}},
|
"setDevChannelState": {Func: rpcSetDevChannelState, Params: []string{"enabled"}},
|
||||||
"getLocalVersion": {Func: rpcGetLocalVersion},
|
"getLocalVersion": {Func: rpcGetLocalVersion},
|
||||||
"getUpdateStatus": {Func: rpcGetUpdateStatus},
|
"getUpdateStatus": {Func: rpcGetUpdateStatus},
|
||||||
|
"checkUpdateComponents": {Func: rpcCheckUpdateComponents, Params: []string{"params", "includePreRelease"}},
|
||||||
"getUpdateStatusChannel": {Func: rpcGetUpdateStatusChannel},
|
"getUpdateStatusChannel": {Func: rpcGetUpdateStatusChannel},
|
||||||
"tryUpdate": {Func: rpcTryUpdate},
|
"tryUpdate": {Func: rpcTryUpdate},
|
||||||
"tryUpdateComponents": {Func: rpcTryUpdateComponents, Params: []string{"components", "includePreRelease", "checkOnly", "resetConfig"}},
|
"tryUpdateComponents": {Func: rpcTryUpdateComponents, Params: []string{"params", "includePreRelease", "resetConfig"}},
|
||||||
"cancelDowngrade": {Func: rpcCancelDowngrade},
|
"cancelDowngrade": {Func: rpcCancelDowngrade},
|
||||||
"getDevModeState": {Func: rpcGetDevModeState},
|
"getDevModeState": {Func: rpcGetDevModeState},
|
||||||
"setDevModeState": {Func: rpcSetDevModeState, Params: []string{"enabled"}},
|
"setDevModeState": {Func: rpcSetDevModeState, Params: []string{"enabled"}},
|
||||||
|
|
|
||||||
73
ota.go
73
ota.go
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Masterminds/semver/v3"
|
"github.com/Masterminds/semver/v3"
|
||||||
"github.com/jetkvm/kvm/internal/ota"
|
"github.com/jetkvm/kvm/internal/ota"
|
||||||
|
|
@ -135,72 +134,56 @@ func rpcGetLocalVersion() (*ota.LocalMetadata, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComponentName represents the name of a component
|
type updateParams struct {
|
||||||
type tryUpdateComponents struct {
|
|
||||||
AppTargetVersion string `json:"app"`
|
AppTargetVersion string `json:"app"`
|
||||||
SystemTargetVersion string `json:"system"`
|
SystemTargetVersion string `json:"system"`
|
||||||
Components string `json:"components,omitempty"` // components is a comma-separated list of components to update
|
Components string `json:"components,omitempty"` // components is a comma-separated list of components to update
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcTryUpdate() error {
|
func rpcTryUpdate() error {
|
||||||
return rpcTryUpdateComponents(tryUpdateComponents{
|
return rpcTryUpdateComponents(updateParams{
|
||||||
AppTargetVersion: "",
|
AppTargetVersion: "",
|
||||||
SystemTargetVersion: "",
|
SystemTargetVersion: "",
|
||||||
}, config.IncludePreRelease, false, false)
|
}, config.IncludePreRelease, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bool, checkOnly bool, resetConfig bool) error {
|
// rpcCheckUpdateComponents checks the update status for the given components
|
||||||
|
func rpcCheckUpdateComponents(params updateParams, includePreRelease bool) (*ota.UpdateStatus, error) {
|
||||||
|
updateParams := ota.UpdateParams{
|
||||||
|
DeviceID: GetDeviceID(),
|
||||||
|
IncludePreRelease: includePreRelease,
|
||||||
|
AppTargetVersion: params.AppTargetVersion,
|
||||||
|
SystemTargetVersion: params.SystemTargetVersion,
|
||||||
|
}
|
||||||
|
if params.Components != "" {
|
||||||
|
updateParams.Components = strings.Split(params.Components, ",")
|
||||||
|
}
|
||||||
|
info, err := otaState.GetUpdateStatus(context.Background(), updateParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to check update: %w", err)
|
||||||
|
}
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rpcTryUpdateComponents(params updateParams, includePreRelease bool, resetConfig bool) error {
|
||||||
updateParams := ota.UpdateParams{
|
updateParams := ota.UpdateParams{
|
||||||
DeviceID: GetDeviceID(),
|
DeviceID: GetDeviceID(),
|
||||||
IncludePreRelease: includePreRelease,
|
IncludePreRelease: includePreRelease,
|
||||||
CheckOnly: checkOnly,
|
|
||||||
ResetConfig: resetConfig,
|
ResetConfig: resetConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info().Interface("components", components).Msg("components")
|
updateParams.AppTargetVersion = params.AppTargetVersion
|
||||||
|
if err := otaState.SetTargetVersion("app", params.AppTargetVersion); err != nil {
|
||||||
currentAppTargetVersion := otaState.GetTargetVersion("app")
|
|
||||||
appTargetVersionChanged := currentAppTargetVersion != components.AppTargetVersion
|
|
||||||
updateParams.AppTargetVersion = components.AppTargetVersion
|
|
||||||
if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil {
|
|
||||||
return fmt.Errorf("failed to set app target version: %w", err)
|
return fmt.Errorf("failed to set app target version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSystemTargetVersion := otaState.GetTargetVersion("system")
|
updateParams.SystemTargetVersion = params.SystemTargetVersion
|
||||||
systemTargetVersionChanged := currentSystemTargetVersion != components.SystemTargetVersion
|
if err := otaState.SetTargetVersion("system", params.SystemTargetVersion); err != nil {
|
||||||
updateParams.SystemTargetVersion = components.SystemTargetVersion
|
|
||||||
if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil {
|
|
||||||
return fmt.Errorf("failed to set system target version: %w", err)
|
return fmt.Errorf("failed to set system target version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if components.Components != "" {
|
if params.Components != "" {
|
||||||
updateParams.Components = strings.Split(components.Components, ",")
|
updateParams.Components = strings.Split(params.Components, ",")
|
||||||
}
|
|
||||||
|
|
||||||
// if it's a check only update, we don't need to try to update, we just need to check if the version is available
|
|
||||||
// and return the error immediately then revert the previous target versions
|
|
||||||
if checkOnly {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
_, err := otaState.GetUpdateStatus(ctx, updateParams)
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// revert the previous target versions
|
|
||||||
if appTargetVersionChanged {
|
|
||||||
if err := otaState.SetTargetVersion("app", currentAppTargetVersion); err != nil {
|
|
||||||
return fmt.Errorf("failed to revert app target version: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if systemTargetVersionChanged {
|
|
||||||
if err := otaState.SetTargetVersion("system", currentSystemTargetVersion); err != nil {
|
|
||||||
return fmt.Errorf("failed to revert system target version: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useSettingsStore } from "@hooks/stores";
|
import { useSettingsStore } from "@hooks/stores";
|
||||||
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
|
import { JsonRpcError, JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
|
||||||
import { useDeviceUiNavigation } from "@hooks/useAppNavigation";
|
import { useDeviceUiNavigation } from "@hooks/useAppNavigation";
|
||||||
import { Button } from "@components/Button";
|
import { Button } from "@components/Button";
|
||||||
import Checkbox, { CheckboxWithLabel } from "@components/Checkbox";
|
import Checkbox, { CheckboxWithLabel } from "@components/Checkbox";
|
||||||
|
|
@ -17,6 +17,8 @@ import { isOnDevice } from "@/main";
|
||||||
import notifications from "@/notifications";
|
import notifications from "@/notifications";
|
||||||
import { m } from "@localizations/messages.js";
|
import { m } from "@localizations/messages.js";
|
||||||
import { sleep } from "@/utils";
|
import { sleep } from "@/utils";
|
||||||
|
import { checkUpdateComponents } from "@/utils/jsonrpc";
|
||||||
|
import { SystemVersionInfo } from "@hooks/useVersion";
|
||||||
|
|
||||||
export default function SettingsAdvancedRoute() {
|
export default function SettingsAdvancedRoute() {
|
||||||
const { send } = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
@ -33,7 +35,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
const [systemVersion, setSystemVersion] = useState<string>("");
|
const [systemVersion, setSystemVersion] = useState<string>("");
|
||||||
const [resetConfig, setResetConfig] = useState(false);
|
const [resetConfig, setResetConfig] = useState(false);
|
||||||
const [versionChangeAcknowledged, setVersionChangeAcknowledged] = useState(false);
|
const [versionChangeAcknowledged, setVersionChangeAcknowledged] = useState(false);
|
||||||
|
const [versionUpdateLoading, setVersionUpdateLoading] = useState(false);
|
||||||
const settings = useSettingsStore();
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -183,34 +185,57 @@ export default function SettingsAdvancedRoute() {
|
||||||
setShowLoopbackWarning(false);
|
setShowLoopbackWarning(false);
|
||||||
}, [applyLoopbackOnlyMode, setShowLoopbackWarning]);
|
}, [applyLoopbackOnlyMode, setShowLoopbackWarning]);
|
||||||
|
|
||||||
const handleVersionUpdate = useCallback(() => {
|
const handleVersionUpdateError = useCallback((error?: JsonRpcError) => {
|
||||||
const params = {
|
notifications.error(
|
||||||
components: {
|
m.advanced_error_version_update({
|
||||||
|
error: error?.data ?? error?.message ?? m.unknown_error()
|
||||||
|
}),
|
||||||
|
{ duration: 1000 * 15 } // 15 seconds
|
||||||
|
);
|
||||||
|
setVersionUpdateLoading(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleVersionUpdate = useCallback(async () => {
|
||||||
|
const components = updateTarget === "both" ? ["app", "system"] : [updateTarget];
|
||||||
|
let versionInfo: SystemVersionInfo | undefined;
|
||||||
|
try {
|
||||||
|
// we do not need to set it to false if check succeeds,
|
||||||
|
// because it will be redirected to the update page later
|
||||||
|
setVersionUpdateLoading(true);
|
||||||
|
versionInfo = await checkUpdateComponents({
|
||||||
|
components: components.join(","),
|
||||||
app: appVersion,
|
app: appVersion,
|
||||||
system: systemVersion,
|
system: systemVersion,
|
||||||
},
|
}, devChannel);
|
||||||
includePreRelease: devChannel,
|
console.log("versionInfo", versionInfo);
|
||||||
checkOnly: true,
|
} catch (error: unknown) {
|
||||||
// no need to reset config for a check only update
|
const jsonRpcError = error as JsonRpcError;
|
||||||
resetConfig: false,
|
handleVersionUpdateError(jsonRpcError);
|
||||||
};
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
send("tryUpdateComponents", params, (resp: JsonRpcResponse) => {
|
if (!versionInfo) {
|
||||||
if ("error" in resp) {
|
handleVersionUpdateError();
|
||||||
notifications.error(
|
return;
|
||||||
m.advanced_error_version_update({ error: resp.error.data || m.unknown_error() })
|
}
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pageParams = new URLSearchParams();
|
|
||||||
pageParams.set("downgrade", "true");
|
|
||||||
pageParams.set("resetConfig", resetConfig.toString());
|
|
||||||
pageParams.set("components", updateTarget === "both" ? "app,system" : updateTarget);
|
|
||||||
|
|
||||||
// Navigate to update page
|
const pageParams = new URLSearchParams();
|
||||||
navigateTo(`/settings/general/update?${pageParams.toString()}`);
|
pageParams.set("downgrade", "true");
|
||||||
});
|
if (components.includes("app") && versionInfo.remote?.appVersion && versionInfo.appDowngradeAvailable) {
|
||||||
}, [updateTarget, appVersion, systemVersion, devChannel, send, navigateTo, resetConfig]);
|
pageParams.set("app", versionInfo.remote?.appVersion);
|
||||||
|
}
|
||||||
|
if (components.includes("system") && versionInfo.remote?.systemVersion && versionInfo.systemDowngradeAvailable) {
|
||||||
|
pageParams.set("system", versionInfo.remote?.systemVersion);
|
||||||
|
}
|
||||||
|
pageParams.set("resetConfig", resetConfig.toString());
|
||||||
|
|
||||||
|
// Navigate to update page
|
||||||
|
navigateTo(`/settings/general/update?${pageParams.toString()}`);
|
||||||
|
}, [
|
||||||
|
updateTarget, appVersion, systemVersion, devChannel,
|
||||||
|
navigateTo, resetConfig, handleVersionUpdateError,
|
||||||
|
setVersionUpdateLoading
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|
@ -374,8 +399,10 @@ export default function SettingsAdvancedRoute() {
|
||||||
(updateTarget === "app" && !appVersion) ||
|
(updateTarget === "app" && !appVersion) ||
|
||||||
(updateTarget === "system" && !systemVersion) ||
|
(updateTarget === "system" && !systemVersion) ||
|
||||||
(updateTarget === "both" && (!appVersion || !systemVersion)) ||
|
(updateTarget === "both" && (!appVersion || !systemVersion)) ||
|
||||||
!versionChangeAcknowledged
|
!versionChangeAcknowledged ||
|
||||||
|
versionUpdateLoading
|
||||||
}
|
}
|
||||||
|
loading={versionUpdateLoading}
|
||||||
onClick={handleVersionUpdate}
|
onClick={handleVersionUpdate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ export default function SettingsGeneralUpdateRoute() {
|
||||||
const { send } = useJsonRpc();
|
const { send } = useJsonRpc();
|
||||||
|
|
||||||
const downgrade = useMemo(() => searchParams.get("downgrade") === "true", [searchParams]);
|
const downgrade = useMemo(() => searchParams.get("downgrade") === "true", [searchParams]);
|
||||||
const updateComponents = useMemo(() => searchParams.get("components") || "", [searchParams]);
|
const customAppVersion = useMemo(() => searchParams.get("app") || "", [searchParams]);
|
||||||
|
const customSystemVersion = useMemo(() => searchParams.get("system") || "", [searchParams]);
|
||||||
const resetConfig = useMemo(() => searchParams.get("resetConfig") === "true", [searchParams]);
|
const resetConfig = useMemo(() => searchParams.get("resetConfig") === "true", [searchParams]);
|
||||||
|
|
||||||
const onClose = useCallback(async () => {
|
const onClose = useCallback(async () => {
|
||||||
|
|
@ -38,18 +39,28 @@ export default function SettingsGeneralUpdateRoute() {
|
||||||
setModalView("updating");
|
setModalView("updating");
|
||||||
}, [send, setModalView]);
|
}, [send, setModalView]);
|
||||||
|
|
||||||
const onConfirmDowngrade = useCallback((system?: string, app?: string) => {
|
const onConfirmDowngrade = useCallback(() => {
|
||||||
|
const components = [];
|
||||||
|
if (customSystemVersion) {
|
||||||
|
components.push("system");
|
||||||
|
}
|
||||||
|
if (customAppVersion) {
|
||||||
|
components.push("app");
|
||||||
|
}
|
||||||
|
|
||||||
send("tryUpdateComponents", {
|
send("tryUpdateComponents", {
|
||||||
components: {
|
params: {
|
||||||
system, app,
|
components: components.join(","),
|
||||||
components: updateComponents
|
app: customAppVersion,
|
||||||
|
system: customSystemVersion,
|
||||||
},
|
},
|
||||||
includePreRelease: true,
|
includePreRelease: false,
|
||||||
checkOnly: false,
|
resetConfig,
|
||||||
resetConfig: resetConfig,
|
}, (resp) => {
|
||||||
|
if ("error" in resp) return;
|
||||||
|
setModalView("updating");
|
||||||
});
|
});
|
||||||
setModalView("updating");
|
}, [send, setModalView, customAppVersion, customSystemVersion, resetConfig]);
|
||||||
}, [send, setModalView, updateComponents, resetConfig]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (otaState.updating) {
|
if (otaState.updating) {
|
||||||
|
|
@ -64,10 +75,12 @@ export default function SettingsGeneralUpdateRoute() {
|
||||||
}, [otaState.error, otaState.updating, setModalView, updateSuccess]);
|
}, [otaState.error, otaState.updating, setModalView, updateSuccess]);
|
||||||
|
|
||||||
return <Dialog
|
return <Dialog
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onConfirmUpdate={onConfirmUpdate}
|
onConfirmUpdate={onConfirmUpdate}
|
||||||
onConfirmDowngrade={onConfirmDowngrade}
|
onConfirmDowngrade={onConfirmDowngrade}
|
||||||
downgrade={downgrade}
|
downgrade={downgrade}
|
||||||
|
customAppVersion={customAppVersion}
|
||||||
|
customSystemVersion={customSystemVersion}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,11 +89,15 @@ export function Dialog({
|
||||||
onConfirmUpdate,
|
onConfirmUpdate,
|
||||||
onConfirmDowngrade,
|
onConfirmDowngrade,
|
||||||
downgrade,
|
downgrade,
|
||||||
|
customAppVersion,
|
||||||
|
customSystemVersion,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
downgrade: boolean;
|
downgrade: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onConfirmUpdate: () => void;
|
onConfirmUpdate: () => void;
|
||||||
onConfirmDowngrade: () => void;
|
onConfirmDowngrade: () => void;
|
||||||
|
customAppVersion?: string;
|
||||||
|
customSystemVersion?: string;
|
||||||
}>) {
|
}>) {
|
||||||
const { navigateTo } = useDeviceUiNavigation();
|
const { navigateTo } = useDeviceUiNavigation();
|
||||||
|
|
||||||
|
|
@ -92,8 +109,7 @@ export function Dialog({
|
||||||
(versionInfo: SystemVersionInfo) => {
|
(versionInfo: SystemVersionInfo) => {
|
||||||
const hasUpdate =
|
const hasUpdate =
|
||||||
versionInfo?.systemUpdateAvailable || versionInfo?.appUpdateAvailable;
|
versionInfo?.systemUpdateAvailable || versionInfo?.appUpdateAvailable;
|
||||||
const hasDowngrade =
|
const hasDowngrade = customSystemVersion !== undefined || customAppVersion !== undefined;
|
||||||
versionInfo?.systemDowngradeAvailable || versionInfo?.appDowngradeAvailable;
|
|
||||||
|
|
||||||
setVersionInfo(versionInfo);
|
setVersionInfo(versionInfo);
|
||||||
|
|
||||||
|
|
@ -105,7 +121,7 @@ export function Dialog({
|
||||||
setModalView("upToDate");
|
setModalView("upToDate");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setModalView, downgrade],
|
[setModalView, downgrade, customAppVersion, customSystemVersion],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onCancelDowngrade = useCallback(() => {
|
const onCancelDowngrade = useCallback(() => {
|
||||||
|
|
@ -137,9 +153,10 @@ export function Dialog({
|
||||||
)}
|
)}
|
||||||
{modalView === "updateDowngradeAvailable" && (
|
{modalView === "updateDowngradeAvailable" && (
|
||||||
<UpdateDowngradeAvailableState
|
<UpdateDowngradeAvailableState
|
||||||
|
appVersion={customAppVersion}
|
||||||
|
systemVersion={customSystemVersion}
|
||||||
onConfirmDowngrade={onConfirmDowngrade}
|
onConfirmDowngrade={onConfirmDowngrade}
|
||||||
onCancelDowngrade={onCancelDowngrade}
|
onCancelDowngrade={onCancelDowngrade}
|
||||||
versionInfo={versionInfo!}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -455,20 +472,19 @@ function UpdateAvailableState({
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateDowngradeAvailableState({
|
function UpdateDowngradeAvailableState({
|
||||||
versionInfo,
|
appVersion,
|
||||||
|
systemVersion,
|
||||||
onConfirmDowngrade,
|
onConfirmDowngrade,
|
||||||
onCancelDowngrade,
|
onCancelDowngrade,
|
||||||
}: {
|
}: {
|
||||||
versionInfo: SystemVersionInfo;
|
appVersion?: string;
|
||||||
onConfirmDowngrade: (system?: string, app?: string) => void;
|
systemVersion?: string;
|
||||||
|
onConfirmDowngrade: () => void;
|
||||||
onCancelDowngrade: () => void;
|
onCancelDowngrade: () => void;
|
||||||
}) {
|
}) {
|
||||||
const confirmDowngrade = useCallback(() => {
|
const confirmDowngrade = useCallback(() => {
|
||||||
onConfirmDowngrade(
|
onConfirmDowngrade();
|
||||||
versionInfo?.remote?.systemVersion || undefined,
|
}, [onConfirmDowngrade]);
|
||||||
versionInfo?.remote?.appVersion || undefined,
|
|
||||||
);
|
|
||||||
}, [versionInfo, onConfirmDowngrade]);
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start justify-start space-y-4 text-left">
|
<div className="flex flex-col items-start justify-start space-y-4 text-left">
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
|
|
@ -479,15 +495,15 @@ function UpdateDowngradeAvailableState({
|
||||||
{m.general_update_downgrade_available_description()}
|
{m.general_update_downgrade_available_description()}
|
||||||
</p>
|
</p>
|
||||||
<p className="mb-4 text-sm text-slate-600 dark:text-slate-300">
|
<p className="mb-4 text-sm text-slate-600 dark:text-slate-300">
|
||||||
{versionInfo?.systemDowngradeAvailable ? (
|
{systemVersion ? (
|
||||||
<>
|
<>
|
||||||
<span className="font-semibold">{m.general_update_system_type()}</span>: {versionInfo?.remote?.systemVersion}
|
<span className="font-semibold">{m.general_update_system_type()}</span>: {systemVersion}
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{versionInfo?.appDowngradeAvailable ? (
|
{appVersion ? (
|
||||||
<>
|
<>
|
||||||
<span className="font-semibold">{m.general_update_application_type()}</span>: {versionInfo?.remote?.appVersion}
|
<span className="font-semibold">{m.general_update_application_type()}</span>: {appVersion}
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -244,3 +244,21 @@ export async function getLocalVersion() {
|
||||||
if (response.error) throw response.error;
|
if (response.error) throw response.error;
|
||||||
return response.result;
|
return response.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface updateParams {
|
||||||
|
app?: string;
|
||||||
|
system?: string;
|
||||||
|
components?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function checkUpdateComponents(params: updateParams, includePreRelease: boolean) {
|
||||||
|
const response = await callJsonRpc<SystemVersionInfo>({
|
||||||
|
method: "checkUpdateComponents",
|
||||||
|
params: {
|
||||||
|
params,
|
||||||
|
includePreRelease,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (response.error) throw response.error;
|
||||||
|
return response.result;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue