Skip to content

Commit

Permalink
Merge pull request #978 from vrc-get/openurl-hack
Browse files Browse the repository at this point in the history
`vcc:` support
  • Loading branch information
anatawa12 committed May 16, 2024
2 parents 56e7169 + c5ac9ef commit 2eca57f
Show file tree
Hide file tree
Showing 17 changed files with 710 additions and 135 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG-gui.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog].

## [Unreleased]
### Added
- `vcc://` support `#978`
- This is enabled by default for macOS and you have to enable manually on Settings page for windows and linux.

### Changed
- Improved project Template selection `#967`
Expand Down
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions vrc-get-gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ async-stream = "0.3.5"
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
sys-locale = "0.3.1"
log-panics = { version = "2", features = ["with-backtrace"] }
url = "2.5.0"
dirs-next = "2.0.0"

[target.'cfg(windows)'.dependencies]
winreg = "0.52.0"

[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2.7"
cocoa = "0.24"

[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
Expand Down
19 changes: 19 additions & 0 deletions vrc-get-gui/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>ALCOM VCC URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>vcc</string>
</array>
</dict>
</array>
</dict>
</plist>
31 changes: 8 additions & 23 deletions vrc-get-gui/app/log/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import {Card, Typography} from "@material-tailwind/react";
import {HNavBar, VStack} from "@/components/layout";
import React, {useEffect} from "react";
import React, {useCallback, useEffect} from "react";
import {LogEntry, utilGetLogEntries} from "@/lib/bindings";
import {listen} from '@tauri-apps/api/event';
import {notoSansMono} from "@/app/fonts";
import {tc} from "@/lib/i18n";
import {useTauriListen} from "@/lib/use-tauri-listen";

export default function Page() {
const [logEntries, setLogEntries] = React.useState<LogEntry[]>([]);
Expand All @@ -14,28 +15,12 @@ export default function Page() {
utilGetLogEntries().then(list => setLogEntries(list.toReversed()));
}, []);

useEffect(() => {
let unlisten: (() => void) | undefined = undefined;
let unlistened = false;

listen("log", (event) => {
setLogEntries((entries) => {
const entry = event.payload as LogEntry;
return [entry, ...entries];
});
}).then((unlistenFn) => {
if (unlistened) {
unlistenFn();
} else {
unlisten = unlistenFn;
}
useTauriListen<LogEntry>("log", useCallback((event) => {
setLogEntries((entries) => {
const entry = event.payload as LogEntry;
return [entry, ...entries];
});

return () => {
unlisten?.();
unlistened = true;
};
}, []);
}, []));

return (
<VStack className={"m-4"}>
Expand Down
49 changes: 38 additions & 11 deletions vrc-get-gui/app/repositories/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from "@material-tailwind/react";
import {useQuery} from "@tanstack/react-query";
import {
deepLinkHasAddRepository, deepLinkTakeAddRepository,
environmentAddRepository,
environmentDownloadRepository,
environmentHideRepository,
Expand All @@ -27,13 +28,14 @@ import {
TauriUserRepository
} from "@/lib/bindings";
import {HNavBar, VStack} from "@/components/layout";
import React, {Suspense, useMemo, useState} from "react";
import React, {Suspense, useCallback, useEffect, useMemo, useState} from "react";
import {MinusCircleIcon, PlusCircleIcon, XCircleIcon} from "@heroicons/react/24/outline";
import {nop} from "@/lib/nop";
import {toastError, toastSuccess, toastThrownError} from "@/lib/toast";
import {toastError, toastNormal, toastSuccess, toastThrownError} from "@/lib/toast";
import {tc, tt} from "@/lib/i18n";
import {InputNoLabel} from "@/components/InputNoLabel";
import {loadManifestWithRetries} from "next/dist/server/load-components";
import {useTauriListen} from "@/lib/use-tauri-listen";

export default function Page(props: {}) {
return <Suspense><PageBody {...props}/></Suspense>
Expand Down Expand Up @@ -68,7 +70,7 @@ function PageBody() {
setState({type: 'normal'});
}

async function addRepository(url: string, headers: { [key: string]: string }) {
const addRepository = useCallback(async function addRepository(url: string, headers: { [key: string]: string }) {
try {
setState({type: 'loadingRepository'});
const info = await environmentDownloadRepository(url, headers);
Expand All @@ -94,7 +96,7 @@ function PageBody() {
toastThrownError(e);
setState({type: 'normal'});
}
}
}, []);

async function removeRepository(id: string) {
try {
Expand All @@ -105,6 +107,24 @@ function PageBody() {
}
}

const processDeepLink = useCallback(async function processDeepLink() {
const data = await deepLinkTakeAddRepository();
if (data == null) return;
await addRepository(data.url, data.headers);
}, [addRepository]);

useTauriListen<null>("deep-link-add-repository", useCallback((_) => {
// noinspection JSIgnoredPromiseFromCall
processDeepLink()
}, [processDeepLink]));

useEffect(() => {
// noinspection JSIgnoredPromiseFromCall
processDeepLink()
// Only for initial load
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

let dialogBody;
switch (state.type) {
case "normal":
Expand Down Expand Up @@ -141,15 +161,17 @@ function PageBody() {
const _exhaustiveCheck: never = state;
}
const dialog = dialogBody ?
<Dialog handler={nop} open><DialogHeader>{tc("vpm repositories:button:add repository")}</DialogHeader>{dialogBody}</Dialog> : null;
<Dialog handler={nop} open><DialogHeader>{tc("vpm repositories:button:add repository")}</DialogHeader>{dialogBody}
</Dialog> : null;

return (
<VStack className={"p-4 overflow-y-auto"}>
<HNavBar className={"flex-shrink-0"}>
<Typography className="cursor-pointer py-1.5 font-bold flex-grow-0">
{tc("vpm repositories:community repositories")}
</Typography>
<Button onClick={() => setState({type: 'enteringRepositoryInfo'})}>{tc("vpm repositories:button:add repository")}</Button>
<Button
onClick={() => setState({type: 'enteringRepositoryInfo'})}>{tc("vpm repositories:button:add repository")}</Button>
</HNavBar>
<main className="flex-shrink flex-grow overflow-hidden flex">
<Card className="w-full overflow-x-auto overflow-y-scroll shadow-none">
Expand Down Expand Up @@ -455,13 +477,17 @@ function EnteringRepositoryInfo(
</table>
</div>
</details>
{foundHeaderNameError && <Typography className={"text-red-700"}>{tc("vpm repositories:hint:invalid header names")}</Typography>}
{foundHeaderValueError && <Typography className={"text-red-700"}>{tc("vpm repositories:hint:invalid header values")}</Typography>}
{foundDuplicateHeader && <Typography className={"text-red-700"}>{tc("vpm repositories:hint:duplicate headers")}</Typography>}
{foundHeaderNameError &&
<Typography className={"text-red-700"}>{tc("vpm repositories:hint:invalid header names")}</Typography>}
{foundHeaderValueError &&
<Typography className={"text-red-700"}>{tc("vpm repositories:hint:invalid header values")}</Typography>}
{foundDuplicateHeader &&
<Typography className={"text-red-700"}>{tc("vpm repositories:hint:duplicate headers")}</Typography>}
</DialogBody>
<DialogFooter>
<Button onClick={cancel}>{tc("general:button:cancel")}</Button>
<Button onClick={onAddRepository} className={"ml-2"} disabled={hasError}>{tc("vpm repositories:button:add repository")}</Button>
<Button onClick={onAddRepository} className={"ml-2"}
disabled={hasError}>{tc("vpm repositories:button:add repository")}</Button>
</DialogFooter>
</>
);
Expand Down Expand Up @@ -525,7 +551,8 @@ function Confirming(
return (
<>
<DialogBody className={"max-h-[50vh] overflow-y-auto font-normal"}>
<Typography className={"font-normal"}>{tc("vpm repositories:dialog:name", {name: repo.display_name})}</Typography>
<Typography
className={"font-normal"}>{tc("vpm repositories:dialog:name", {name: repo.display_name})}</Typography>
<Typography className={"font-normal"}>{tc("vpm repositories:dialog:url", {url: repo.url})}</Typography>
{Object.keys(headers).length > 0 && (
<>
Expand Down
43 changes: 38 additions & 5 deletions vrc-get-gui/app/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import {Button, Card, Checkbox, Input, Typography} from "@material-tailwind/reac
import Link from "next/link";
import {useQuery} from "@tanstack/react-query";
import {
deepLinkInstallVcc,
environmentGetSettings,
environmentPickProjectBackupPath,
environmentPickProjectDefaultPath,
environmentPickUnity,
environmentPickUnityHub, environmentSetBackupFormat,
environmentPickUnityHub,
environmentSetBackupFormat,
environmentSetLanguage,
environmentSetShowPrereleasePackages,
TauriEnvironmentSettings,
Expand All @@ -22,7 +24,8 @@ import {VGOption, VGSelect} from "@/components/select";
import {useFilePickerFunction} from "@/lib/use-file-picker-dialog";
import {emit} from "@tauri-apps/api/event";
import {shellOpen} from "@/lib/shellOpen";
import { loadOSApi } from "@/lib/os";
import {loadOSApi} from "@/lib/os";
import type {OsType} from "@tauri-apps/api/os";

export default function Page() {
const result = useQuery({
Expand Down Expand Up @@ -71,6 +74,15 @@ function Settings(
const [pickProjectDefaultPath, projectDefaultDialog] = useFilePickerFunction(environmentPickProjectDefaultPath);
const [pickProjectBackupPath, projectBackupDialog] = useFilePickerFunction(environmentPickProjectBackupPath);

const [osType, setOsType] = React.useState<OsType>("Windows_NT");

React.useEffect(() => {
(async () => {
const os = await loadOSApi();
setOsType(await os.type());
})();
}, [])

const selectUnityHub = async () => {
try {
const result = await pickUnityHub();
Expand Down Expand Up @@ -206,6 +218,16 @@ function Settings(
shellOpen(url.toString())
}

const installVccProtocol = async () => {
try {
await deepLinkInstallVcc();
toastSuccess(tc("settings:toast:vcc scheme installed"));
} catch (e) {
console.error(e);
toastThrownError(e)
}
}


return (
<main className="flex flex-col gap-2 flex-shrink overflow-y-auto flex-grow">
Expand Down Expand Up @@ -238,7 +260,8 @@ function Settings(
</Typography>
<div className={"flex gap-1"}>
<Input className="flex-auto" value={settings.default_project_path} disabled/>
<Button className={"flex-none px-4"} onClick={selectProjectDefaultFolder}>{tc("general:button:select")}</Button>
<Button className={"flex-none px-4"}
onClick={selectProjectDefaultFolder}>{tc("general:button:select")}</Button>
</div>
</Card>
<Card className={"flex-shrink-0 p-4"}>
Expand All @@ -250,7 +273,8 @@ function Settings(
</Typography>
<div className={"flex gap-1"}>
<Input className="flex-auto" value={settings.project_backup_path} disabled/>
<Button className={"flex-none px-4"} onClick={selectProjectBackupFolder}>{tc("general:button:select")}</Button>
<Button className={"flex-none px-4"}
onClick={selectProjectBackupFolder}>{tc("general:button:select")}</Button>
</div>
</div>
<div className="mt-2">
Expand Down Expand Up @@ -296,10 +320,19 @@ function Settings(
<Button onClick={() => emit("tauri://update")}>{tc("settings:check update")}</Button>
</div>
</Card>
{osType != "Darwin" && <Card className={"flex-shrink-0 p-4"}>
<h2>{tc("settings:vcc scheme")}</h2>
<Typography className={"whitespace-normal"}>
{tc("settings:vcc scheme description")}
</Typography>
<div>
<Button onClick={installVccProtocol}>{tc("settings:register vcc scheme")}</Button>
</div>
</Card>}
<Card className={"flex-shrink-0 p-4"}>
<h2>{tc("settings:report issue")}</h2>
<div>
<Button onClick={reportIssue}>{tc("settings:button:open issue")}</Button>
<Button onClick={reportIssue}>{tc("settings:button:open issue")}</Button>
</div>
</Card>
<Card className={"flex-shrink-0 p-4"}>
Expand Down

0 comments on commit 2eca57f

Please sign in to comment.