This commit is contained in:
2024-06-12 20:27:08 +08:00
parent df448b68af
commit 82077fc12a
23 changed files with 2464 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class AllowLAN extends PopupMenu.PopupMenuItem {
constructor() {
super("允许局域网连接");
}
}
+47
View File
@@ -0,0 +1,47 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { GLib } from "@girs/glib-2.0";
import { Gio } from "@girs/gio-2.0";
import * as Main from "@girs/gnome-shell/ui/main";
import { registerGObjectClass } from "../utils/gjs";
import { ExtensionMetadata } from "@girs/gnome-shell/extensions/extension";
import { getCoreVersion } from "../core";
@registerGObjectClass
export class Configure extends PopupMenu.PopupSubMenuMenuItem {
constructor(options: { metadata: ExtensionMetadata }) {
super("配置");
const separator = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addAction("config", () => {});
this.menu.addMenuItem(separator);
this.menu.addAction("打开配置文件夹", () => {
const file = Gio.File.new_for_path(
`${GLib.get_user_data_dir()}/${options.metadata.uuid}`
);
const appInfo = Gio.AppInfo.get_default_for_type(
file
.query_info(
"standard::content-type",
Gio.FileQueryInfoFlags.NONE,
null
)
.get_content_type()!,
false
);
if (appInfo) {
appInfo.launch([file], null);
}
});
this.menu.addAction("托管配置", () => {});
const versionIt = new PopupMenu.PopupMenuItem('点击查看版本号')
versionIt.connect('activate', () => {
const version = getCoreVersion();
log(version)
})
this.menu.addMenuItem(versionIt)
}
}
+12
View File
@@ -0,0 +1,12 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import * as Main from "@girs/gnome-shell/ui/main";
import { registerGObjectClass } from "../utils/gjs";
import { fetch } from "../utils/fetch";
@registerGObjectClass
export class Enabler extends PopupMenu.PopupMenuItem {
constructor() {
super("启用");
}
}
+10
View File
@@ -0,0 +1,10 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class Exit extends PopupMenu.PopupMenuItem {
constructor() {
super("退出");
}
}
+58
View File
@@ -0,0 +1,58 @@
import * as PanelMenu from "@girs/gnome-shell/ui/panelMenu";
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { St } from "@girs/st-14";
import { registerGObjectClass } from "../utils/gjs";
import { Enabler } from "./enabler";
import { Mode } from "./mode";
import { ProxyEnv } from "./proxy-env";
import { SystemProxy } from "./system-proxy";
import { StartAtBoot } from "./start-at-boot";
import { AllowLAN } from "./allow-lan";
import { Configure } from "./configure";
import { Settings } from "./settings";
import { ExtensionMetadata } from "@girs/gnome-shell/extensions/extension";
@registerGObjectClass
export class Indicator extends PanelMenu.Button {
metadata: ExtensionMetadata;
constructor(options: { metadata: ExtensionMetadata }) {
super(0.0, _("Clash Indicator"));
this.metadata = options.metadata;
this.add_child(
new St.Icon({
icon_name: "face-smile-symbolic",
style_class: "system-status-icon",
})
);
this.menu = this.menu as PopupMenu.PopupMenu
const enabler = new Enabler();
this.menu.addMenuItem(enabler);
const mode = new Mode();
this.menu.addMenuItem(mode);
const proxyEnv = new ProxyEnv();
this.menu.addMenuItem(proxyEnv);
const systemProxy = new SystemProxy();
this.menu.addMenuItem(systemProxy);
const startAtBoot = new StartAtBoot();
this.menu.addMenuItem(startAtBoot);
const allowLAN = new AllowLAN();
this.menu.addMenuItem(allowLAN);
const settings = new Settings();
this.menu.addMenuItem(settings);
const configure = new Configure({
metadata: this.metadata,
});
this.menu.addMenuItem(configure);
}
}
+21
View File
@@ -0,0 +1,21 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class Mode extends PopupMenu.PopupSubMenuMenuItem {
constructor() {
super("出站模式");
this.label.text = "出站模式(规则)";
this.menu.addAction("规则模式", () => {
globalThis.log("修改为规则模式");
});
this.menu.addAction("全局模式", () => {
globalThis.log("修改为全局模式");
});
this.menu.addAction("直连模式", () => {
globalThis.log("修改为直连模式");
});
}
}
+14
View File
@@ -0,0 +1,14 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class ProxyEnv extends PopupMenu.PopupMenuItem {
constructor() {
super("复制环境变量");
this.connect("activate", () => {
globalThis.log("复制环境变量");
});
}
}
+10
View File
@@ -0,0 +1,10 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class Settings extends PopupMenu.PopupMenuItem {
constructor() {
super("打开设置面板");
}
}
+10
View File
@@ -0,0 +1,10 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class StartAtBoot extends PopupMenu.PopupMenuItem {
constructor() {
super("开机启动");
}
}
+10
View File
@@ -0,0 +1,10 @@
import * as PopupMenu from "@girs/gnome-shell/ui/popupMenu";
import { registerGObjectClass } from "../utils/gjs";
@registerGObjectClass
export class SystemProxy extends PopupMenu.PopupMenuItem {
constructor() {
super("系统代理");
}
}
+9
View File
@@ -0,0 +1,9 @@
import { fetch } from "../utils/fetch";
function startClash() {}
export function getCoreVersion() {
const dataText = fetch.get('/version')
const {version} = JSON.parse(dataText || '{}')
return version
}
+60
View File
@@ -0,0 +1,60 @@
/* extension.js
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import {
Extension,
ExtensionMetadata,
gettext as _,
} from "@girs/gnome-shell/extensions/extension";
import { GLib } from "@girs/glib-2.0";
import * as Main from "@girs/gnome-shell/ui/main";
import { Indicator } from "./components/indicator";
export default class ClashIndicatorExtension extends Extension {
private indicator!: Indicator | null;
constructor(metadata: ExtensionMetadata) {
super(metadata);
this.init();
}
init() {
const dataDir = GLib.build_filenamev([
GLib.get_user_data_dir(),
this.metadata.uuid,
]);
log(dataDir);
if (!GLib.file_test(dataDir, GLib.FileTest.EXISTS)) {
GLib.mkdir_with_parents(dataDir, 0o755);
log(dataDir);
}
}
enable() {
this.indicator = new Indicator({
metadata: this.metadata,
});
Main.panel.addToStatusArea(this.uuid, this.indicator);
}
disable() {
this.indicator?.destroy();
this.indicator = null;
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"name": "Clash Indicator",
"description": "A clash user interface.",
"uuid": "clash-indicator@indusy.gmail.com",
"shell-version": [
"46"
]
}
View File
+25
View File
@@ -0,0 +1,25 @@
import { Soup } from "@girs/soup-3.0";
import { GLib } from "@girs/glib-2.0";
const baseUrl = "http://localhost:9097";
function get(url: string) {
const session = new Soup.Session();
const message = Soup.Message.new("GET", baseUrl + url);
try {
const dataBytes = session.send_and_read(message, null);
const textDecoder = new TextDecoder();
const dataText = textDecoder.decode(dataBytes.get_data()!);
dataBytes.get_data()?.forEach((x) => {
log(x);
});
return dataText;
} catch (error) {}
}
export const fetch = {
get,
};
+29
View File
@@ -0,0 +1,29 @@
import GObject from "@girs/gobject-2.0";
export function registerGObjectClass<
K,
T extends {
metaInfo?: GObject.MetaInfo<any, any, any>;
new (...params: any[]): K;
}
>(target: T) {
if (Object.prototype.hasOwnProperty.call(target, "metaInfo")) {
// @ts-ignore
return GObject.registerClass<K, T>(
target.metaInfo!,
target
) as typeof target;
} else {
// @ts-ignore
return GObject.registerClass<K, T>(target) as typeof target;
}
}
export interface SignalRepresentationType<A extends any[]> {
param_types: A;
accumulator: number;
}
export type SignalsDefinition<T extends string> = {
[key in T]: SignalRepresentationType<any> | Record<string, never>;
};