Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Commit

Permalink
🚀 Client App [Tauri] (#27)
Browse files Browse the repository at this point in the history
* Client App [Tauri]

[+] fix(global.d.ts): declare TauriAPI interface globally and add missing methods
[+] fix(sync.ts): import getClientConfig from client config and add alternative fix for tauri
[+] fix(utils.ts): import getClientConfig from client config and update copyToClipboard and downloadAs functions to use Tauri API if available

* Whitelist Client App [Tauri]

[+] fix(cors/route.ts): add alternative fix for Tauri by checking if isApp is true before applying CORS restrictions
[+] fix(openai/route.ts): add alternative fix for Tauri by checking if isApp is true before applying CORS restrictions

* Fix Export DownloadAs) Client App [Tauri]

Ref issue : [Bug] 'export' button does not work Yidadaa#2933

[+] fix(global.d.ts): change parameter name from command to text in invoke function
[+] feat(sync.ts): improve backup file name generation to include date and time
[+] fix(tauri.conf.json): disable updater functionality

* Exporter Client App [Tauri]

Reff Issue : [Bug] 'export' button does not work ChatGPTNextWeb#2884
[+] fix(exporter.tsx): fix download function to handle saving file in Tauri app
[+] feat(exporter.tsx): add support for downloading file in Tauri app
[+] fix(exporter.tsx): fix download function to handle saving file in Tauri app
[+] feat(exporter.tsx): add support for downloading file in Tauri app

* Refactor Client App [Tauri]

[+] refactor(exporter.tsx): remove unused isMobile variable

* Client App [Tauri] [Authentication page]

Ref : UI Page [Auth Page] ChatGPTNextWeb#2933
[+] feat(auth.tsx): add authentication page UI and functionality for app clients
[+] fix(cn.ts): update unauthorized access error message for app clients
[+] fix(en.ts): update unauthorized access error message for app clients

* Client App [Tauri] [ChangeLog Page]

[+] refactor(changelog.tsx): refactor fetchData function to improve readability and limit the number of displayed changes for isApp
[+] feat(changelog.tsx): add support for displaying commit date in the changelog table

* Client App [Tauri] [Dev Stuff] [ChangeLog Page]

[+] fix(build.ts): change git log command to retrieve only the latest commit information
[+] feat(client.ts): update getClientConfig function to include commit message description in the build config

* Revert "Whitelist Client App [Tauri]"

This reverts commit 469eaff.

* 🚀 Client App [Tauri]

Reff Issue : [Bug] 'export' button does not work ChatGPTNextWeb#2884

[+] feat(global.d.ts): add support for Tauri API in global window interface
[+] fix(utils.ts): fix typo in copyToClipboard function, change invoke to writeText

* Client App [Tauri] [Authentication page]

Ref : UI Page [Auth Page] ChatGPTNextWeb#2933

[+] chore(auth.tsx): remove unused import of useEffect
[+] feat(auth.tsx): conditionally render input access code and input access token based on whether it's an app
  • Loading branch information
H0llyW00dzZ authored Oct 1, 2023
1 parent 39619cc commit 2e948b4
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 55 deletions.
33 changes: 14 additions & 19 deletions app/components/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useAccessStore } from "../store";
import Locale from "../locales";

import BotIcon from "../icons/bot.svg";
import { useEffect } from "react";
import { getClientConfig } from "../config/client";

export function AuthPage() {
Expand All @@ -18,13 +17,6 @@ export function AuthPage() {
const resetAccessCode = () => { access.updateCode(""); access.updateToken(""); }; // Reset access code to empty string
const goPrivacy = () => navigate(Path.PrivacyPage);

useEffect(() => {
if (getClientConfig()?.isApp) {
navigate(Path.Settings);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<div className={styles["auth-page"]}>
<div className={`no-dark ${styles["auth-logo"]}`}>
Expand All @@ -34,16 +26,19 @@ export function AuthPage() {
<div className={styles["auth-title"]}>{Locale.Auth.Title}</div>
<div className={styles["auth-tips"]}>{Locale.Auth.Tips}</div>

<input
className={styles["auth-input"]}
type="password"
placeholder={Locale.Auth.Input}
value={access.accessCode}
onChange={(e) => {
access.updateCode(e.currentTarget.value);
}}
/>
{!access.hideUserApiKey ? (
{!getClientConfig()?.isApp && ( // Conditionally render the input access code based on whether it's an app
<input
className={styles["auth-input"]}
type="password"
placeholder={Locale.Auth.Input}
value={access.accessCode}
onChange={(e) => {
access.updateCode(e.currentTarget.value);
}}
/>
)}

{getClientConfig()?.isApp && ( // Conditionally render the input access token based on whether it's an app
<>
<div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div>
<input
Expand All @@ -56,7 +51,7 @@ export function AuthPage() {
}}
/>
</>
) : null}
)}

<div className={styles["auth-actions"]}>
<IconButton
Expand Down
16 changes: 13 additions & 3 deletions app/components/changelog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,21 @@ export function ChangeLog(props: { onClose?: () => void }) {
const fetchData = async () => {
const commitInfo = getClientConfig();

let table = `## 🚀 What's Changed ? ${commitInfo?.commitDate ? new Date(parseInt(commitInfo.commitDate)).toLocaleString() : 'Unknown Date'} 🗓️\n`;
let table = `## 🚀 What's Changed ? ${
commitInfo?.commitDate
? new Date(parseInt(commitInfo.commitDate)).toLocaleString()
: "Unknown Date"
} 🗓️\n`;

if (commitInfo?.commitMessage.description) {
const changes = commitInfo?.commitMessage.description.map((change: string) => `\n\n\n ${change}\n\n`).join("\n\n\n");
table += `\n\n\n ${commitInfo?.commitMessage.summary}\n\n\n${changes}\n\n\n`;
let changes: string[] = commitInfo.commitMessage.description;
if (getClientConfig()?.isApp && changes.length > 10) {
changes = changes.slice(0, 10); // Limit to 10 messages for isApp
}
const changesFormatted = changes
.map((change: string) => `\n\n\n ${change}\n\n`)
.join("\n\n\n");
table += `\n\n\n ${commitInfo?.commitMessage.summary}\n\n\n${changesFormatted}\n\n\n`;
} else {
table += `###${commitInfo?.commitMessage.summary}###\nNo changes\n\n`;
}
Expand Down
80 changes: 62 additions & 18 deletions app/components/exporter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -433,26 +433,46 @@ export function ImagePreviewer(props: {

const isMobile = useMobileScreen();

const download = () => {
const download = async () => {
showToast(Locale.Export.Image.Toast);
const dom = previewRef.current;
if (!dom) return;
toPng(dom)
.then((blob) => {
if (!blob) return;

if (isMobile || getClientConfig()?.isApp) {
showImageModal(blob);

const isApp = getClientConfig()?.isApp;

try {
const blob = await toPng(dom);
if (!blob) return;

if (isMobile || (isApp && window.__TAURI__)) {
if (isApp && window.__TAURI__) {
const result = await window.__TAURI__.dialog.save({
defaultPath: `${props.topic}.png`,
});

if (result !== null) {
const response = await fetch(blob);
const buffer = await response.arrayBuffer();
const uint8Array = new Uint8Array(buffer);
await window.__TAURI__.fs.writeBinaryFile(result, uint8Array);
showToast(Locale.Download.Success);
} else {
showToast(Locale.Download.Failed);
}
} else {
const link = document.createElement("a");
link.download = `${props.topic}.png`;
link.href = blob;
link.click();
refreshPreview();
showImageModal(blob);
}
})
.catch((e) => console.log("[Export Image] ", e));
};
} else {
const link = document.createElement("a");
link.download = `${props.topic}.png`;
link.href = blob;
link.click();
refreshPreview();
}
} catch (error) {
showToast(Locale.Download.Failed);
}
};

const refreshPreview = () => {
const dom = previewRef.current;
Expand Down Expand Up @@ -566,14 +586,38 @@ export function MarkdownPreviewer(props: {
const copy = () => {
copyToClipboard(mdText);
};
const download = () => {
const download = async () => {
const isApp = getClientConfig()?.isApp;
const blob = new Blob([mdText], { type: "text/markdown" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${props.topic}.md`;
link.click();
};

if (isApp && window.__TAURI__) {
try {
const result = await window.__TAURI__.dialog.save({
defaultPath: `${props.topic}.md`,
});

if (result !== null) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
const uint8Array = new Uint8Array(buffer);
await window.__TAURI__.fs.writeBinaryFile(result, uint8Array);
showToast(Locale.Download.Success);
} else {
showToast(Locale.Download.Failed);
}
} catch (error) {
showToast(Locale.Download.Failed);
}
} else {
link.click();
}

URL.revokeObjectURL(url);
};
return (
<>
<PreviewActions
Expand Down
6 changes: 3 additions & 3 deletions app/config/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ export const getBuildConfig = () => {
.toString()
.trim();
const commitHash: string = childProcess
.execSync('git log --pretty=format:"%H" -n 1')
.execSync('git log --pretty=format:"%H" -n 10')
.toString()
.trim();
const commitMessage: string = childProcess
.execSync('git log --pretty=format:"%B" -n 5')
.execSync('git log --pretty=format:"%B" -n 10')
.toString()
.trim();
const Author: string = childProcess
.execSync('git log --pretty=format:"%an" -n 1')
.toString()
.trim();
const coAuthorLine: string = childProcess
.execSync('git log --format="%h %(trailers:key=Co-authored-by)" -n 5')
.execSync('git log --format="%h %(trailers:key=Co-authored-by)" -n 10')
.toString()
.trim();
const coAuthorMatch: RegExpMatchArray | null = coAuthorLine.match(
Expand Down
20 changes: 18 additions & 2 deletions app/config/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@ import { BuildConfig, getBuildConfig } from "./build";
export function getClientConfig() {
if (typeof document !== "undefined") {
// client side
return JSON.parse(queryMeta("config")) as BuildConfig;
const buildConfig = JSON.parse(queryMeta("config")) as BuildConfig;
const commitMessage = buildConfig.commitMessage?.description?.slice(0, 10);
return {
...buildConfig,
commitMessage: {
...buildConfig.commitMessage,
description: commitMessage,
},
};
}

if (typeof process !== "undefined") {
// server side
return getBuildConfig();
const buildConfig = getBuildConfig();
const commitMessage = buildConfig.commitMessage?.description?.slice(0, 10);
return {
...buildConfig,
commitMessage: {
...buildConfig.commitMessage,
description: commitMessage,
},
};
}
}

Expand Down
8 changes: 7 additions & 1 deletion app/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ declare module "*.svg";

declare interface Window {
__TAURI__?: {
[x: string]: any;
writeText(text: string): Promise<void>;
invoke(command: string, payload?: Record<string, unknown>): Promise<any>;
dialog: {
save(options?: Record<string, unknown>): Promise<string | null>;
};
fs: {
writeBinaryFile(path: string, data: Uint8Array): Promise<void>;
};
};
}
2 changes: 1 addition & 1 deletion app/locales/cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const cn = {
WIP: "该功能仍在开发中……",
Error: {
Unauthorized: isApp
? "检测到无效 API Key,请前往[设置](/#/settings)页检查 API Key 是否配置正确。"
? "未经授权的访问,请在 [auth](/#/auth) 页面输入您的 OpenAI API Key。"
: "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码,或者在[设置](/#/settings)页填入你自己的 OpenAI API Key。",
Content_Policy: {
Title:
Expand Down
2 changes: 1 addition & 1 deletion app/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const en: LocaleType = {
WIP: "Coming Soon...",
Error: {
Unauthorized: isApp
? "Invalid API Key, please check it in [Settings](/#/settings) page."
? "Unauthorized access, please enter your OpenAI API Key in [auth](/#/auth) page."
: "Unauthorized access, please enter access code in [auth](/#/auth) page, or enter your OpenAI API Key.",
Content_Policy: {
Title:
Expand Down
11 changes: 9 additions & 2 deletions app/store/sync.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getClientConfig } from "../config/client";
import { Updater } from "../typing";
import { ApiPath, STORAGE_KEY, StoreKey } from "../constant";
import { createPersistStore } from "../utils/store";
Expand Down Expand Up @@ -63,6 +64,8 @@ const DEFAULT_SYNC_STATE = {
syncing: false,
lockclient: false,
};
// alternative fix for tauri
const isApp = !!getClientConfig()?.isApp;

export const useSyncStore = createPersistStore(
DEFAULT_SYNC_STATE,
Expand All @@ -82,8 +85,12 @@ export const useSyncStore = createPersistStore(

export() {
const state = getLocalAppState();
const fileName = `Backup-${new Date().toLocaleString()}`;
downloadAs(state, fileName);
const datePart = isApp
? `${new Date().toLocaleDateString().replace(/\//g, '_')} ${new Date().toLocaleTimeString().replace(/:/g, '_')}`
: new Date().toLocaleString();

const fileName = `Backup-${datePart}`;
downloadAs((state), fileName);
},

async import() {
Expand Down
11 changes: 6 additions & 5 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getClientConfig } from "./config/client";
import { useEffect, useState } from "react";
import { showToast } from "./components/ui-lib";
import Locale from "./locales";
Expand All @@ -6,9 +7,12 @@ export function trimTopic(topic: string) {
return topic.replace(/[",.!?]*$/, "");
}

const isApp = !!getClientConfig()?.isApp;

export async function copyToClipboard(text: string) {

try {
if (window.__TAURI__) {
if (isApp && window.__TAURI__) {
window.__TAURI__.writeText(text);
} else {
await navigator.clipboard.writeText(text);
Expand Down Expand Up @@ -44,10 +48,7 @@ export async function downloadAs(text: object, filename: string) {
});

if (result !== null) {
await window.__TAURI__.fs.writeBinaryFile(
result,
Array.from(uint8Array),
);
await window.__TAURI__.fs.writeBinaryFile(result, Uint8Array.from(uint8Array));
showToast(Locale.Download.Success);
} else {
showToast(Locale.Download.Failed);
Expand Down
3 changes: 3 additions & 0 deletions src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
"startDragging": true,
"unmaximize": true,
"unminimize": true
},
"fs": {
"all": true
}
},
"bundle": {
Expand Down

0 comments on commit 2e948b4

Please sign in to comment.