wip
parent
df448b68af
commit
82077fc12a
|
|
@ -0,0 +1 @@
|
||||||
|
export {}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"name": "gnome-shell-extension-clash-indicator",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "rimraf dist",
|
||||||
|
"build": "rollup -c",
|
||||||
|
"build:dev": "rollup -c --environment DEBUG",
|
||||||
|
"test": "sh test.sh",
|
||||||
|
"push": "sh push.sh"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"packageManager": "pnpm@9.3.0+sha512.ee7b93e0c2bd11409c6424f92b866f31d3ea1bef5fbe47d3c7500cdc3c9668833d2e55681ad66df5b640c61fa9dc25d546efa54d76d7f8bf54b13614ac293631",
|
||||||
|
"devDependencies": {
|
||||||
|
"@girs/clutter-14": "14.0.0-4.0.0-beta.5",
|
||||||
|
"@girs/gio-2.0": "2.78.0-3.3.0",
|
||||||
|
"@girs/gjs": "^3.3.0",
|
||||||
|
"@girs/glib-2.0": "2.78.0-3.3.0",
|
||||||
|
"@girs/gnome-shell": "46.0.0-beta8",
|
||||||
|
"@girs/gobject-2.0": "2.78.0-3.3.0",
|
||||||
|
"@girs/gtk-4.0": "4.12.5-3.3.0",
|
||||||
|
"@girs/soup-3.0": "3.4.4-3.3.0",
|
||||||
|
"@girs/st-14": "14.0.0-4.0.0-beta.5",
|
||||||
|
"@rollup/plugin-commonjs": "^26.0.1",
|
||||||
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
|
"@rollup/plugin-terser": "^0.4.4",
|
||||||
|
"rimraf": "^5.0.7",
|
||||||
|
"rollup": "^4.18.0",
|
||||||
|
"rollup-plugin-copy": "^3.5.0",
|
||||||
|
"rollup-plugin-tsconfig-paths": "^1.5.2",
|
||||||
|
"rollup-plugin-typescript2": "^0.36.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
ln -s ${PWD}/dist/ ${HOME}/.local/share/gnome-shell/extensions/clash-indicator@indusy.gmail.com
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import { defineConfig } from "rollup";
|
||||||
|
|
||||||
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||||
|
import json from "@rollup/plugin-json";
|
||||||
|
import terser from "@rollup/plugin-terser";
|
||||||
|
import typescript from "rollup-plugin-typescript2";
|
||||||
|
import copy from "rollup-plugin-copy";
|
||||||
|
import tsconfigPaths from 'rollup-plugin-tsconfig-paths'
|
||||||
|
|
||||||
|
/** @type {(options: {matches: RegExp[]}) => import("rollup").Plugin} */
|
||||||
|
const excludeImports = (options) => {
|
||||||
|
const matches = options.matches;
|
||||||
|
return {
|
||||||
|
name: "exclude-imports-plugin",
|
||||||
|
resolveId(source, importer) {
|
||||||
|
if (importer) {
|
||||||
|
if (matches.some((r) => r.test(source))) {
|
||||||
|
return {
|
||||||
|
id: source,
|
||||||
|
external: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = defineConfig(() => {
|
||||||
|
const commonPlugs = [
|
||||||
|
nodeResolve(),
|
||||||
|
commonjs(),
|
||||||
|
json(),
|
||||||
|
typescript({ check: false }),
|
||||||
|
excludeImports({
|
||||||
|
matches: [/^gi:/, /^resource:/],
|
||||||
|
}),
|
||||||
|
// @ts-ignore
|
||||||
|
].concat(process.env.DEBUG ? null : terser(), tsconfigPaths());
|
||||||
|
|
||||||
|
/** @type {import('rollup').RollupOptions} */
|
||||||
|
const extensionModule = {
|
||||||
|
input: "src/extension.ts",
|
||||||
|
output: {
|
||||||
|
name: "[name].js",
|
||||||
|
dir: "dist",
|
||||||
|
format: "es",
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
...commonPlugs,
|
||||||
|
copy({
|
||||||
|
targets: [
|
||||||
|
{
|
||||||
|
src: "src/metadata.json",
|
||||||
|
dest: "dist",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return [extensionModule];
|
||||||
|
});
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|
@ -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("允许局域网连接");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("启用");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("退出");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("修改为直连模式");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("复制环境变量");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("打开设置面板");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("开机启动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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("系统代理");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "Clash Indicator",
|
||||||
|
"description": "A clash user interface.",
|
||||||
|
"uuid": "clash-indicator@indusy.gmail.com",
|
||||||
|
"shell-version": [
|
||||||
|
"46"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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,
|
||||||
|
};
|
||||||
|
|
@ -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>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
export G_MESSAGES_DEBUG=
|
||||||
|
export MUTTER_DEBUG_DUMMY_MODE_SPECS=1366x768
|
||||||
|
export SHELL_DEBUG=all
|
||||||
|
|
||||||
|
dbus-run-session -- \
|
||||||
|
gnome-shell --nested \
|
||||||
|
--wayland
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"types": [
|
||||||
|
"@girs/gjs",
|
||||||
|
"@girs/gtk-4.0",
|
||||||
|
"@girs/gnome-shell/extensions/global"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["src", "define.d.ts"]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue