update.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant";
  2. import { api } from "../client/api";
  3. import { getClientConfig } from "../config/client";
  4. import { createPersistStore } from "../utils/store";
  5. import ChatGptIcon from "../icons/chatgpt.png";
  6. import Locale from "../locales";
  7. const ONE_MINUTE = 60 * 1000;
  8. const isApp = !!getClientConfig()?.isApp;
  9. function formatVersionDate(t: string) {
  10. const d = new Date(+t);
  11. const year = d.getUTCFullYear();
  12. const month = d.getUTCMonth() + 1;
  13. const day = d.getUTCDate();
  14. return [
  15. year.toString(),
  16. month.toString().padStart(2, "0"),
  17. day.toString().padStart(2, "0"),
  18. ].join("");
  19. }
  20. type VersionType = "date" | "tag";
  21. async function getVersion(type: VersionType) {
  22. if (type === "date") {
  23. const data = (await (await fetch(FETCH_COMMIT_URL)).json()) as {
  24. commit: {
  25. author: { name: string; date: string };
  26. };
  27. sha: string;
  28. }[];
  29. const remoteCommitTime = data[0].commit.author.date;
  30. const remoteId = new Date(remoteCommitTime).getTime().toString();
  31. return remoteId;
  32. } else if (type === "tag") {
  33. const data = (await (await fetch(FETCH_TAG_URL)).json()) as {
  34. commit: { sha: string; url: string };
  35. name: string;
  36. }[];
  37. return data.at(0)?.name;
  38. }
  39. }
  40. export const useUpdateStore = createPersistStore(
  41. {
  42. versionType: "tag" as VersionType,
  43. lastUpdate: 0,
  44. version: "unknown",
  45. remoteVersion: "",
  46. used: 0,
  47. subscription: 0,
  48. lastUpdateUsage: 0,
  49. },
  50. (set, get) => ({
  51. formatVersion(version: string) {
  52. if (get().versionType === "date") {
  53. version = formatVersionDate(version);
  54. }
  55. return version;
  56. },
  57. async getLatestVersion(force = false) {
  58. const versionType = get().versionType;
  59. let version =
  60. versionType === "date"
  61. ? getClientConfig()?.commitDate
  62. : getClientConfig()?.version;
  63. set(() => ({ version }));
  64. const shouldCheck = Date.now() - get().lastUpdate > 2 * 60 * ONE_MINUTE;
  65. if (!force && !shouldCheck) return;
  66. set(() => ({
  67. lastUpdate: Date.now(),
  68. }));
  69. try {
  70. const remoteId = await getVersion(versionType);
  71. set(() => ({
  72. remoteVersion: remoteId,
  73. }));
  74. if (window.__TAURI__?.notification && isApp) {
  75. // Check if notification permission is granted
  76. await window.__TAURI__?.notification.isPermissionGranted().then((granted) => {
  77. if (!granted) {
  78. return;
  79. } else {
  80. // Request permission to show notifications
  81. window.__TAURI__?.notification.requestPermission().then((permission) => {
  82. if (permission === 'granted') {
  83. if (version === remoteId) {
  84. // Show a notification using Tauri
  85. window.__TAURI__?.notification.sendNotification({
  86. title: "ChatGPT Next Web",
  87. body: `${Locale.Settings.Update.IsLatest}`,
  88. icon: `${ChatGptIcon.src}`,
  89. sound: "Default"
  90. });
  91. } else {
  92. const updateMessage = Locale.Settings.Update.FoundUpdate(`${remoteId}`);
  93. // Show a notification for the new version using Tauri
  94. window.__TAURI__?.notification.sendNotification({
  95. title: "ChatGPT Next Web",
  96. body: updateMessage,
  97. icon: `${ChatGptIcon.src}`,
  98. sound: "Default"
  99. });
  100. }
  101. }
  102. });
  103. }
  104. });
  105. }
  106. console.log("[Got Upstream] ", remoteId);
  107. } catch (error) {
  108. console.error("[Fetch Upstream Commit Id]", error);
  109. }
  110. },
  111. async updateUsage(force = false) {
  112. const overOneMinute = Date.now() - get().lastUpdateUsage >= ONE_MINUTE;
  113. if (!overOneMinute && !force) return;
  114. set(() => ({
  115. lastUpdateUsage: Date.now(),
  116. }));
  117. try {
  118. const usage = await api.llm.usage();
  119. if (usage) {
  120. set(() => ({
  121. used: usage.used,
  122. subscription: usage.total,
  123. }));
  124. }
  125. } catch (e) {
  126. console.error((e as Error).message);
  127. }
  128. },
  129. }),
  130. {
  131. name: StoreKey.Update,
  132. version: 1,
  133. },
  134. );