Skip to content

Commit

Permalink
Show newest ver at the top of setting (#1194)
Browse files Browse the repository at this point in the history
  • Loading branch information
logancyang authored Feb 5, 2025
1 parent e114d3c commit 52bd93d
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 42 deletions.
32 changes: 0 additions & 32 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
TFile,
TFolder,
WorkspaceLeaf,
requestUrl,
} from "obsidian";

export default class CopilotPlugin extends Plugin {
Expand Down Expand Up @@ -327,35 +326,4 @@ export default class CopilotPlugin extends Plugin {
metadata: doc.metadata,
}));
}

// TODO: Add a setting for this. Disable for now.
private async checkForUpdates(): Promise<void> {
try {
const response = await requestUrl({
url: "https://api.github.com/repos/logancyang/obsidian-copilot/releases/latest",
method: "GET",
});

const latestVersion = response.json.tag_name.replace("v", "");
if (this.isNewerVersion(latestVersion, this.manifest.version)) {
new Notice(
`A newer version (${latestVersion}) of Obsidian Copilot is available. You are currently on version ${this.manifest.version}. Please update to the latest version.`,
10000
);
}
} catch (error) {
console.error("Failed to check for updates:", error);
}
}

private isNewerVersion(latest: string, current: string): boolean {
const latestParts = latest.split(".").map(Number);
const currentParts = current.split(".").map(Number);

for (let i = 0; i < 3; i++) {
if (latestParts[i] > currentParts[i]) return true;
if (latestParts[i] < currentParts[i]) return false;
}
return false;
}
}
64 changes: 54 additions & 10 deletions src/settings/v2/SettingsMainV2.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from "react";
import { Cog, Cpu, Database, Wrench } from "lucide-react";
import { ResetSettingsConfirmModal } from "@/components/modals/ResetSettingsConfirmModal";
import { Button } from "@/components/ui/button";
import { TabContent, TabItem, type TabItem as TabItemType } from "@/components/ui/setting-tabs";
import { TabProvider, useTab } from "@/contexts/TabContext";
import CopilotPlugin from "@/main";
import { resetSettings } from "@/settings/model";
import { checkLatestVersion, isNewerVersion } from "@/utils";
import { Cog, Cpu, Database, Wrench } from "lucide-react";
import React, { useEffect, useState } from "react";
import AdvancedSettings from "./components/AdvancedSettings";
import BasicSettings from "./components/BasicSettings";
import ModelSettings from "./components/ModelSettings";
import AdvancedSettings from "./components/AdvancedSettings";
import QASettings from "./components/QASettings";
import { TabProvider, useTab } from "@/contexts/TabContext";
import { ResetSettingsConfirmModal } from "@/components/modals/ResetSettingsConfirmModal";
import { resetSettings } from "@/settings/model";
import CopilotPlugin from "@/main";
import { Button } from "@/components/ui/button";

const TAB_IDS = ["basic", "model", "QA", "advanced"] as const;
type TabId = (typeof TAB_IDS)[number];
Expand Down Expand Up @@ -89,6 +90,24 @@ interface SettingsMainV2Props {
const SettingsMainV2: React.FC<SettingsMainV2Props> = ({ plugin }) => {
// Add a key state that we'll change when resetting
const [resetKey, setResetKey] = React.useState(0);
const [latestVersion, setLatestVersion] = useState<string | null>(null);
const [updateError, setUpdateError] = useState<string | null>(null);

useEffect(() => {
// Check version when settings tab is opened
const checkForUpdates = async () => {
const { version, error } = await checkLatestVersion();
if (error) {
console.error("Version check failed:", error);
setUpdateError(error);
} else if (version) {
setLatestVersion(version);
setUpdateError(null);
}
};

checkForUpdates();
}, [plugin.manifest.version]); // Only re-run if plugin version changes

const handleReset = async () => {
const modal = new ResetSettingsConfirmModal(app, async () => {
Expand All @@ -99,13 +118,38 @@ const SettingsMainV2: React.FC<SettingsMainV2Props> = ({ plugin }) => {
modal.open();
};

const isNewerVersionAvailable =
latestVersion && isNewerVersion(latestVersion, plugin.manifest.version);

return (
<TabProvider>
<div>
<div className="flex flex-col gap-2">
<h1 className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
<div>
Copilot Settings <span className="text-xs">v{plugin.manifest.version}</span>
<div className="flex items-center gap-2">
<span>Copilot Settings</span>
<span className="text-xs text-muted">
v{plugin.manifest.version}
{updateError ? (
<span className="text-error" title={updateError}>
{" "}
(update check failed)
</span>
) : (
latestVersion && (
<>
{isNewerVersionAvailable ? (
<span className="text-accent" title="A new version is available">
{" "}
(latest: v{latestVersion})
</span>
) : (
<span className="text-accent"> (up to date)</span>
)}
</>
)
)}
</span>
</div>
<div className="self-end sm:self-auto">
<Button variant="outline" size="sm" onClick={handleReset}>
Expand Down
36 changes: 36 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -823,3 +823,39 @@ export function debounce<T extends (...args: any[]) => void>(
timeout = setTimeout(() => func(...args), wait);
};
}

/**
* Compare two semantic version strings.
* @returns true if latest version is newer than current version
*/
export function isNewerVersion(latest: string, current: string): boolean {
const latestParts = latest.split(".").map(Number);
const currentParts = current.split(".").map(Number);

for (let i = 0; i < 3; i++) {
if (latestParts[i] > currentParts[i]) return true;
if (latestParts[i] < currentParts[i]) return false;
}
return false;
}

/**
* Check for latest version from GitHub releases.
* @returns latest version string or error message
*/
export async function checkLatestVersion(): Promise<{
version: string | null;
error: string | null;
}> {
try {
const response = await requestUrl({
url: "https://api.github.com/repos/logancyang/obsidian-copilot/releases/latest",
method: "GET",
});
const version = response.json.tag_name.replace("v", "");
return { version, error: null };
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Failed to check for updates";
return { version: null, error: errorMessage };
}
}

0 comments on commit 52bd93d

Please sign in to comment.