Merge pull request #117 from luminous-devs/feat/optional-updater
Make auto update is optional
This commit is contained in:
@@ -1,9 +1,24 @@
|
|||||||
import { getVersion } from '@tauri-apps/api/app';
|
import { getVersion } from '@tauri-apps/api/app';
|
||||||
|
import { relaunch } from '@tauri-apps/plugin-process';
|
||||||
|
import { Update, check } from '@tauri-apps/plugin-updater';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
export function AboutScreen() {
|
export function AboutScreen() {
|
||||||
const [version, setVersion] = useState('');
|
const [version, setVersion] = useState('');
|
||||||
|
const [newUpdate, setNewUpdate] = useState<Update>(null);
|
||||||
|
|
||||||
|
const checkUpdate = async () => {
|
||||||
|
const update = await check();
|
||||||
|
if (!update) toast.info('There is no update available');
|
||||||
|
setNewUpdate(update);
|
||||||
|
};
|
||||||
|
|
||||||
|
const installUpdate = async () => {
|
||||||
|
await newUpdate.downloadAndInstall();
|
||||||
|
await relaunch();
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function loadVersion() {
|
async function loadVersion() {
|
||||||
@@ -20,19 +35,38 @@ export function AboutScreen() {
|
|||||||
<img src="/icon.png" alt="Lume's logo" className="w-16 shrink-0" />
|
<img src="/icon.png" alt="Lume's logo" className="w-16 shrink-0" />
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-xl font-semibold">Lume</h1>
|
<h1 className="text-xl font-semibold">Lume</h1>
|
||||||
<p className="text-neutral-700 dark:text-neutral-300">Version {version}</p>
|
<p className="text-sm font-medium text-neutral-700 dark:text-neutral-300">
|
||||||
|
Version {version}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto mt-4 flex w-full max-w-xs flex-col gap-2">
|
<div className="mx-auto mt-4 flex w-full max-w-xs flex-col gap-2">
|
||||||
|
{!newUpdate ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => checkUpdate()}
|
||||||
|
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
Check for update
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => installUpdate()}
|
||||||
|
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-blue-500 text-sm font-medium text-white hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
Install {newUpdate.version}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<Link
|
<Link
|
||||||
to="https://lume.nu"
|
to="https://lume.nu"
|
||||||
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||||
>
|
>
|
||||||
Website
|
Website
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="https://github.com/luminous-devs/lume/issues"
|
to="https://github.com/luminous-devs/lume/issues"
|
||||||
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 text-sm font-medium hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||||
>
|
>
|
||||||
Report a issue
|
Report a issue
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { DarkIcon, LightIcon, SystemModeIcon } from '@shared/icons';
|
|||||||
export function GeneralSettingScreen() {
|
export function GeneralSettingScreen() {
|
||||||
const { db } = useStorage();
|
const { db } = useStorage();
|
||||||
const [settings, setSettings] = useState({
|
const [settings, setSettings] = useState({
|
||||||
|
autoupdate: false,
|
||||||
autolaunch: false,
|
autolaunch: false,
|
||||||
outbox: false,
|
outbox: false,
|
||||||
media: true,
|
media: true,
|
||||||
@@ -59,6 +60,13 @@ export function GeneralSettingScreen() {
|
|||||||
setSettings((prev) => ({ ...prev, hashtag: !settings.hashtag }));
|
setSettings((prev) => ({ ...prev, hashtag: !settings.hashtag }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleAutoupdate = async () => {
|
||||||
|
await db.createSetting('autoupdate', String(+!settings.autoupdate));
|
||||||
|
db.settings.autoupdate = !settings.autoupdate;
|
||||||
|
// update state
|
||||||
|
setSettings((prev) => ({ ...prev, autoupdate: !settings.autoupdate }));
|
||||||
|
};
|
||||||
|
|
||||||
const toggleNofitication = async () => {
|
const toggleNofitication = async () => {
|
||||||
if (settings.notification) return;
|
if (settings.notification) return;
|
||||||
|
|
||||||
@@ -82,6 +90,12 @@ export function GeneralSettingScreen() {
|
|||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
|
if (item.key === 'autoupdate')
|
||||||
|
setSettings((prev) => ({
|
||||||
|
...prev,
|
||||||
|
autoupdate: !!parseInt(item.value),
|
||||||
|
}));
|
||||||
|
|
||||||
if (item.key === 'outbox')
|
if (item.key === 'outbox')
|
||||||
setSettings((prev) => ({
|
setSettings((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -114,6 +128,19 @@ export function GeneralSettingScreen() {
|
|||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-lg">
|
<div className="mx-auto w-full max-w-lg">
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-col gap-6">
|
||||||
|
<div className="flex w-full items-center justify-between">
|
||||||
|
<div className="flex items-center gap-8">
|
||||||
|
<div className="w-24 shrink-0 text-end text-sm font-semibold">Updater</div>
|
||||||
|
<div className="text-sm">Auto download new update at Login</div>
|
||||||
|
</div>
|
||||||
|
<Switch.Root
|
||||||
|
checked={settings.autoupdate}
|
||||||
|
onClick={() => toggleAutoupdate()}
|
||||||
|
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
|
||||||
|
>
|
||||||
|
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
|
||||||
|
</Switch.Root>
|
||||||
|
</div>
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-center justify-between">
|
||||||
<div className="flex items-center gap-8">
|
<div className="flex items-center gap-8">
|
||||||
<div className="w-24 shrink-0 text-end text-sm font-semibold">Startup</div>
|
<div className="w-24 shrink-0 text-end text-sm font-semibold">Startup</div>
|
||||||
|
|||||||
@@ -20,13 +20,18 @@ export class LumeStorage {
|
|||||||
public db: Database;
|
public db: Database;
|
||||||
public account: Account | null;
|
public account: Account | null;
|
||||||
public platform: Platform | null;
|
public platform: Platform | null;
|
||||||
public settings: { outbox: boolean; media: boolean; hashtag: boolean };
|
public settings: {
|
||||||
|
autoupdate: boolean;
|
||||||
|
outbox: boolean;
|
||||||
|
media: boolean;
|
||||||
|
hashtag: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
constructor(sqlite: Database, platform: Platform) {
|
constructor(sqlite: Database, platform: Platform) {
|
||||||
this.db = sqlite;
|
this.db = sqlite;
|
||||||
this.account = null;
|
this.account = null;
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.settings = { outbox: false, media: true, hashtag: true };
|
this.settings = { autoupdate: false, outbox: false, media: true, hashtag: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async secureSave(key: string, value: string) {
|
public async secureSave(key: string, value: string) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const StorageContext = createContext<StorageContext>({
|
|||||||
db: undefined,
|
db: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
const StorageInstance = () => {
|
||||||
const [db, setDB] = useState<LumeStorage>(undefined);
|
const [db, setDB] = useState<LumeStorage>(undefined);
|
||||||
const [isNewVersion, setIsNewVersion] = useState(false);
|
const [isNewVersion, setIsNewVersion] = useState(false);
|
||||||
|
|
||||||
@@ -33,6 +33,8 @@ const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
if (!lumeStorage.account) await lumeStorage.getActiveAccount();
|
if (!lumeStorage.account) await lumeStorage.getActiveAccount();
|
||||||
|
|
||||||
const settings = await lumeStorage.getAllSettings();
|
const settings = await lumeStorage.getAllSettings();
|
||||||
|
let autoUpdater = false;
|
||||||
|
|
||||||
if (settings) {
|
if (settings) {
|
||||||
settings.forEach((item) => {
|
settings.forEach((item) => {
|
||||||
if (item.key === 'outbox') lumeStorage.settings.outbox = !!parseInt(item.value);
|
if (item.key === 'outbox') lumeStorage.settings.outbox = !!parseInt(item.value);
|
||||||
@@ -41,16 +43,23 @@ const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
|
|
||||||
if (item.key === 'hashtag')
|
if (item.key === 'hashtag')
|
||||||
lumeStorage.settings.hashtag = !!parseInt(item.value);
|
lumeStorage.settings.hashtag = !!parseInt(item.value);
|
||||||
|
|
||||||
|
if (item.key === 'autoupdate') {
|
||||||
|
if (parseInt(item.value)) autoUpdater = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// check update
|
if (autoUpdater) {
|
||||||
const update = await check();
|
// check update
|
||||||
if (update) {
|
const update = await check();
|
||||||
setIsNewVersion(true);
|
// install new version
|
||||||
|
if (update) {
|
||||||
|
setIsNewVersion(true);
|
||||||
|
|
||||||
await update.downloadAndInstall();
|
await update.downloadAndInstall();
|
||||||
await relaunch();
|
await relaunch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setDB(lumeStorage);
|
setDB(lumeStorage);
|
||||||
@@ -66,6 +75,12 @@ const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
if (!db) initLumeStorage();
|
if (!db) initLumeStorage();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
return { db, isNewVersion };
|
||||||
|
};
|
||||||
|
|
||||||
|
const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
||||||
|
const { db, isNewVersion } = StorageInstance();
|
||||||
|
|
||||||
if (!db)
|
if (!db)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -93,7 +108,7 @@ const StorageProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
<div className="absolute bottom-5 right-5 inline-flex items-center gap-2.5">
|
<div className="absolute bottom-5 right-5 inline-flex items-center gap-2.5">
|
||||||
<LoaderIcon className="h-6 w-6 animate-spin text-blue-500" />
|
<LoaderIcon className="h-6 w-6 animate-spin text-blue-500" />
|
||||||
<p className="font-semibold">
|
<p className="font-semibold">
|
||||||
{isNewVersion ? 'Found a new version, updating' : 'Checking for updates...'}
|
{isNewVersion ? 'Found a new version, updating...' : 'Starting...'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user