beast-agent 2.35.1 → 2.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -1
- package/src/agent/store.js +73 -25
- package/src/renderer/i18n.js +4 -0
- package/src/renderer/index.html +0 -1
- package/src/renderer/renderer.js +53 -13
- package/src/renderer/style.css +16 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beast-agent",
|
|
3
3
|
"productName": "Beast Agent",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.36.1",
|
|
5
5
|
"description": "Ultra-fast local agent shell for Windows.",
|
|
6
6
|
"author": "algokodcom (AlgoKod)",
|
|
7
7
|
"license": "MIT",
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"dist": "electron-builder --win nsis portable",
|
|
41
41
|
"test": "node --test \"tests/**/*.test.js\"",
|
|
42
42
|
"release": "node scripts/release.js",
|
|
43
|
+
"skillsweb:sync": "node skillsweb/sync-builtins.js",
|
|
44
|
+
"skillsweb:deploy": "node skillsweb/sync-builtins.js && cd skillsweb && firebase deploy --only hosting:skills",
|
|
43
45
|
"postinstall": "node scripts/fix-electron.js --soft",
|
|
44
46
|
"prepublishOnly": "node scripts/swap-electron.js deps",
|
|
45
47
|
"postpublish": "node scripts/swap-electron.js devdeps"
|
package/src/agent/store.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
/* SKILLS STORE: topluluk skill mağazası.
|
|
4
4
|
- Yerel DB : %APPDATA%\beast\store\skills.json (yüklenen skill'ler, dosyalar gömülü)
|
|
5
5
|
- İstatistik DB : %APPDATA%\beast\store\stats.json (installs/likes — makine başına)
|
|
6
|
-
-
|
|
6
|
+
- Veri kaynağı : beastagent-skills.web.app (builtins.json + community.json)
|
|
7
|
+
erişilemezse GitHub raw /store/skills.json, o da yoksa offline cache
|
|
7
8
|
- Kurulum hedefi : %APPDATA%\beast\skills\<id>\ (skills.scan() otomatik görür)
|
|
8
9
|
Trending/Stars sıralaması renderer'da skorla yapılır; burada ham veri döner.
|
|
9
10
|
Beast Kodu ASLA paylaşılmaz — yalnız sha256 türevi parmak izi (beastId) kullanılır. */
|
|
@@ -14,6 +15,10 @@ const crypto = require('crypto');
|
|
|
14
15
|
const { beastRoot } = require('./memory');
|
|
15
16
|
const skills = require('./skills');
|
|
16
17
|
|
|
18
|
+
const SITE_URL = 'https://skills.algokod.com';
|
|
19
|
+
const SITE_FALLBACK_URL = 'https://beastagent-skills.web.app';
|
|
20
|
+
const SITE_COMMUNITY_URLS = [SITE_URL + '/community.json', SITE_FALLBACK_URL + '/community.json'];
|
|
21
|
+
const SITE_BUILTINS_URLS = [SITE_URL + '/builtins.json', SITE_FALLBACK_URL + '/builtins.json'];
|
|
17
22
|
const COMMUNITY_URL = 'https://raw.githubusercontent.com/algokodcom/beast-agent/main/store/skills.json';
|
|
18
23
|
const MAX_FILES = 20;
|
|
19
24
|
const MAX_FILE_BYTES = 200 * 1024;
|
|
@@ -33,6 +38,9 @@ function statsFile() {
|
|
|
33
38
|
function communityCacheFile() {
|
|
34
39
|
return path.join(storeDir(), 'community.json');
|
|
35
40
|
}
|
|
41
|
+
function builtinsCacheFile() {
|
|
42
|
+
return path.join(storeDir(), 'builtins.json');
|
|
43
|
+
}
|
|
36
44
|
|
|
37
45
|
function readJson(p, fallback) {
|
|
38
46
|
try {
|
|
@@ -83,34 +91,68 @@ function slugify(s) {
|
|
|
83
91
|
);
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
/* ----------
|
|
94
|
+
/* ---------- veri kaynağı (site → GitHub → cache) ---------- */
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
const MEMO_MS = 5 * 60 * 1000;
|
|
97
|
+
const memo = { community: null, communityAt: 0, builtins: null, builtinsAt: 0 };
|
|
98
|
+
|
|
99
|
+
async function fetchJson(url, timeoutMs = 6000) {
|
|
100
|
+
const ctl = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
101
|
+
const t = setTimeout(() => {
|
|
102
|
+
try {
|
|
103
|
+
ctl && ctl.abort();
|
|
104
|
+
} catch {}
|
|
105
|
+
}, timeoutMs);
|
|
89
106
|
try {
|
|
90
|
-
const
|
|
91
|
-
const t = setTimeout(() => {
|
|
92
|
-
try {
|
|
93
|
-
ctl && ctl.abort();
|
|
94
|
-
} catch {}
|
|
95
|
-
}, timeoutMs);
|
|
96
|
-
const r = await fetch(COMMUNITY_URL, { signal: ctl ? ctl.signal : undefined });
|
|
97
|
-
clearTimeout(t);
|
|
107
|
+
const r = await fetch(url, { signal: ctl ? ctl.signal : undefined });
|
|
98
108
|
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
writeJson(communityCacheFile(), j);
|
|
103
|
-
} catch {}
|
|
104
|
-
return j.skills;
|
|
105
|
-
}
|
|
106
|
-
return [];
|
|
107
|
-
} catch {
|
|
108
|
-
/* offline: son iyi kopyadan devam */
|
|
109
|
-
const cached = readJson(communityCacheFile(), { skills: [] });
|
|
110
|
-
return Array.isArray(cached.skills) ? cached.skills : [];
|
|
109
|
+
return await r.json();
|
|
110
|
+
} finally {
|
|
111
|
+
clearTimeout(t);
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
/* Topluluk indeksi: önce SİTE (skills.algokod.com), sonra web.app yedeği, sonra GitHub raw */
|
|
116
|
+
async function fetchCommunity(timeoutMs = 6000) {
|
|
117
|
+
if (memo.community && Date.now() - memo.communityAt < MEMO_MS) return memo.community;
|
|
118
|
+
for (const url of [...SITE_COMMUNITY_URLS, COMMUNITY_URL]) {
|
|
119
|
+
try {
|
|
120
|
+
const j = await fetchJson(url, timeoutMs);
|
|
121
|
+
if (j && Array.isArray(j.skills)) {
|
|
122
|
+
try {
|
|
123
|
+
writeJson(communityCacheFile(), j);
|
|
124
|
+
} catch {}
|
|
125
|
+
memo.community = j.skills;
|
|
126
|
+
memo.communityAt = Date.now();
|
|
127
|
+
return j.skills;
|
|
128
|
+
}
|
|
129
|
+
} catch {}
|
|
130
|
+
}
|
|
131
|
+
/* offline: son iyi kopyadan devam */
|
|
132
|
+
const cached = readJson(communityCacheFile(), { skills: [] });
|
|
133
|
+
return Array.isArray(cached.skills) ? cached.skills : [];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Yerleşik skill vitrini: sitedeki builtins.json (offline'da diske cache) */
|
|
137
|
+
async function fetchBuiltins(timeoutMs = 6000) {
|
|
138
|
+
if (memo.builtins && Date.now() - memo.builtinsAt < MEMO_MS) return memo.builtins;
|
|
139
|
+
for (const url of SITE_BUILTINS_URLS) {
|
|
140
|
+
try {
|
|
141
|
+
const j = await fetchJson(url, timeoutMs);
|
|
142
|
+
if (j && Array.isArray(j.skills)) {
|
|
143
|
+
try {
|
|
144
|
+
writeJson(builtinsCacheFile(), j);
|
|
145
|
+
} catch {}
|
|
146
|
+
memo.builtins = j.skills;
|
|
147
|
+
memo.builtinsAt = Date.now();
|
|
148
|
+
return j.skills;
|
|
149
|
+
}
|
|
150
|
+
} catch {}
|
|
151
|
+
}
|
|
152
|
+
const cached = readJson(builtinsCacheFile(), { skills: [] });
|
|
153
|
+
return Array.isArray(cached.skills) ? cached.skills : [];
|
|
154
|
+
}
|
|
155
|
+
|
|
114
156
|
function mergeStats(entry, stats) {
|
|
115
157
|
const st = stats[entry.id] || {};
|
|
116
158
|
return {
|
|
@@ -122,18 +164,24 @@ function mergeStats(entry, stats) {
|
|
|
122
164
|
};
|
|
123
165
|
}
|
|
124
166
|
|
|
125
|
-
/* Birleşik liste: topluluk + yerel
|
|
167
|
+
/* Birleşik liste: site (yerleşikler + topluluk) + yerel; aynı id'de yerel kazanır.
|
|
168
|
+
Yerleşikler `builtin:true` taşır — kart "Kurulu" gösterir, Trending/Stars'ta görünür. */
|
|
126
169
|
async function list(beastCode) {
|
|
127
|
-
const [community] = await Promise.all([fetchCommunity()]);
|
|
170
|
+
const [community, builtins] = await Promise.all([fetchCommunity(), fetchBuiltins()]);
|
|
128
171
|
const db = loadLocal();
|
|
129
172
|
const stats = loadStats();
|
|
130
173
|
const byId = new Map();
|
|
131
174
|
for (const e of community) {
|
|
132
175
|
if (e && e.id && e.files && e.files['SKILL.md']) byId.set(e.id, e);
|
|
133
176
|
}
|
|
177
|
+
for (const b of builtins) {
|
|
178
|
+
if (!b || !b.id || !b.files || !b.files['SKILL.md']) continue;
|
|
179
|
+
byId.set(b.id, { ...b, builtin: true });
|
|
180
|
+
}
|
|
134
181
|
for (const e of db.skills) if (e && e.id) byId.set(e.id, e);
|
|
135
182
|
const entries = [...byId.values()].map((e) => mergeStats(e, stats));
|
|
136
183
|
const installed = new Set(skills.scan().map((s) => path.basename(path.dirname(s.path))));
|
|
184
|
+
for (const e of entries) if (e.builtin) installed.add(e.id);
|
|
137
185
|
return {
|
|
138
186
|
ok: true,
|
|
139
187
|
beastId: beastFingerprint(beastCode),
|
package/src/renderer/i18n.js
CHANGED
|
@@ -620,6 +620,8 @@
|
|
|
620
620
|
store_update: 'Güncelle',
|
|
621
621
|
store_installs: 'kurulum',
|
|
622
622
|
store_likes: 'beğeni',
|
|
623
|
+
store_builtin: 'Yerleşik',
|
|
624
|
+
store_builtin_note: 'Ajanla birlikte gelir',
|
|
623
625
|
store_empty_trending: 'Mağaza henüz boş — ilk skill\u2019i sen yükle!',
|
|
624
626
|
store_empty_stars: 'Henüz yıldız skill yok — uzun süre popüler olanlar buraya yükselir.',
|
|
625
627
|
store_offline: 'Topluluk indeksine ulaşılamadı (offline) — yerel kayıtlar gösteriliyor.',
|
|
@@ -1411,6 +1413,8 @@
|
|
|
1411
1413
|
store_update: 'Update',
|
|
1412
1414
|
store_installs: 'installs',
|
|
1413
1415
|
store_likes: 'likes',
|
|
1416
|
+
store_builtin: 'Built-in',
|
|
1417
|
+
store_builtin_note: 'Ships with the agent',
|
|
1414
1418
|
store_empty_trending: 'The store is empty — be the first to upload a skill!',
|
|
1415
1419
|
store_empty_stars: 'No star skills yet — long-time popular ones rise here.',
|
|
1416
1420
|
store_offline: 'Community index unreachable (offline) — showing local entries.',
|
package/src/renderer/index.html
CHANGED
|
@@ -615,7 +615,6 @@
|
|
|
615
615
|
<nav id="storeTabs">
|
|
616
616
|
<button class="stab active" data-stab="trending" data-i18n="store_tab_trending">Trending</button>
|
|
617
617
|
<button class="stab" data-stab="stars" data-i18n="store_tab_stars">Stars</button>
|
|
618
|
-
<button class="stab" data-stab="upload" data-i18n="store_tab_upload">Upload</button>
|
|
619
618
|
</nav>
|
|
620
619
|
<div id="storePane"></div>
|
|
621
620
|
</div>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -7676,33 +7676,73 @@ function closeStore() {
|
|
|
7676
7676
|
$('#storeOverlay').hidden = true;
|
|
7677
7677
|
}
|
|
7678
7678
|
|
|
7679
|
+
/* Mağaza kart ikonları — kapağı olmayan skill'lere otomatik SVG ikon atanır
|
|
7680
|
+
(site builtins.json / community kayıtlarındaki `icon` alanı kullanılır). */
|
|
7681
|
+
const STORE_ICONS = {
|
|
7682
|
+
grid: '<rect x="3.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="13.5" width="7" height="7" rx="1.5"/>',
|
|
7683
|
+
'file-text': '<path d="M13 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V9z"/><path d="M13 3v6h6M9 13h6M9 17h4"/>',
|
|
7684
|
+
wrench: '<path d="M15.5 3.5a5.5 5.5 0 0 0-4.6 8.5L4 18.9a2 2 0 0 0 2.8 2.8l6.9-6.9a5.5 5.5 0 0 0 6.9-7.3l-3.2 3.2-2.8-.7-.7-2.8z"/>',
|
|
7685
|
+
zap: '<path d="M13 2 4.5 13.5H11L10 22l8.5-11.5H12z"/>',
|
|
7686
|
+
bar: '<path d="M5 20V11M12 20V5M19 20v-6"/>',
|
|
7687
|
+
shield: '<path d="M12 3l7.5 3v5.5c0 4.6-3.1 7.9-7.5 9.5-4.4-1.6-7.5-4.9-7.5-9.5V6z"/><path d="m9 12 2 2 4-4"/>',
|
|
7688
|
+
book: '<path d="M4 4.5A2.5 2.5 0 0 1 6.5 2H20v16H6.5A2.5 2.5 0 0 0 4 20.5z"/><path d="M4 20.5A2.5 2.5 0 0 1 6.5 18H20v4H6.5A2.5 2.5 0 0 1 4 19.5z"/>',
|
|
7689
|
+
cpu: '<rect x="6.5" y="6.5" width="11" height="11" rx="2"/><rect x="10" y="10" width="4" height="4" rx="1"/><path d="M9 3v2.5M15 3v2.5M9 18.5V21M15 18.5V21M3 9h2.5M3 15h2.5M18.5 9H21M18.5 15H21"/>',
|
|
7690
|
+
flask: '<path d="M9.5 3h5M10.5 3v6.2L5 18.5A2 2 0 0 0 6.8 21h10.4a2 2 0 0 0 1.8-2.5L13.5 9.2V3"/><path d="M7.5 15h9"/>',
|
|
7691
|
+
news: '<path d="M4 5h13a2 2 0 0 1 2 2v11a2 2 0 0 0 2 2H6a2 2 0 0 1-2-2z"/><path d="M7 9h7M7 13h7M7 17h4"/>',
|
|
7692
|
+
compass: '<circle cx="12" cy="12" r="8.5"/><path d="m15.5 8.5-2 5-5 2 2-5z"/>',
|
|
7693
|
+
mail: '<rect x="3" y="5.5" width="18" height="13" rx="2"/><path d="m3.5 7 8.5 6 8.5-6"/>',
|
|
7694
|
+
activity: '<path d="M3 12h4l2.5-6 4 12L16 12h5"/>',
|
|
7695
|
+
bulb: '<path d="M9 18h6M10 21h4"/><path d="M12 3a6 6 0 0 1 3.5 10.9c-.6.5-1 1.3-1 2.1h-5c0-.8-.4-1.6-1-2.1A6 6 0 0 1 12 3z"/>',
|
|
7696
|
+
clipboard: '<rect x="5" y="4.5" width="14" height="16" rx="2"/><path d="M9 4.5V3.8A1.8 1.8 0 0 1 10.8 2h2.4A1.8 1.8 0 0 1 15 3.8v.7M9 10h6M9 14h6M9 18h3"/>',
|
|
7697
|
+
play: '<path d="M7 4.5v15l12-7.5z"/>',
|
|
7698
|
+
bug: '<rect x="8" y="7" width="8" height="11" rx="4"/><path d="M9.5 7a2.5 2.5 0 0 1 5 0M3.5 11H8M16 11h4.5M4.5 17H8M16 17h3.5M6 6.5 8 9M18 6.5 16 9"/>',
|
|
7699
|
+
'check-circle': '<circle cx="12" cy="12" r="8.5"/><path d="m8.5 12.2 2.4 2.4 4.6-4.8"/>',
|
|
7700
|
+
search: '<circle cx="11" cy="11" r="6.5"/><path d="m16.2 16.2 4.3 4.3"/>',
|
|
7701
|
+
trending: '<path d="m3.5 17 5.5-5.5 3.5 3.5 7-7"/><path d="M15 8h5v5"/>',
|
|
7702
|
+
download: '<path d="M12 3v11M7.5 10.5 12 15l4.5-4.5"/><path d="M4 18v1.5A1.5 1.5 0 0 0 5.5 21h13A1.5 1.5 0 0 0 20 19.5V18"/>',
|
|
7703
|
+
heart: '<path d="M12 20s-7-4.4-7-9.4A4.1 4.1 0 0 1 12 7.6a4.1 4.1 0 0 1 7 3c0 5-7 9.4-7 9.4z"/>',
|
|
7704
|
+
box: '<path d="M3.5 7.5 12 3l8.5 4.5v9L12 21l-8.5-4.5z"/><path d="M3.5 7.5 12 12l8.5-4.5M12 12v9"/>',
|
|
7705
|
+
user: '<circle cx="12" cy="8" r="3.6"/><path d="M5 20c.6-3.4 3.5-5.4 7-5.4s6.4 2 7 5.4"/>',
|
|
7706
|
+
paw: '<circle cx="7" cy="9" r="2.2"/><circle cx="12" cy="7" r="2.2"/><circle cx="17" cy="9" r="2.2"/><path d="M12 12c-3.2 0-5.5 2.4-5.5 4.6 0 1.6 1.3 2.4 2.9 2.4 1 0 1.8-.4 2.6-.4s1.6.4 2.6.4c1.6 0 2.9-.8 2.9-2.4C17.5 14.4 15.2 12 12 12Z"/>',
|
|
7707
|
+
};
|
|
7708
|
+
|
|
7709
|
+
function storeIconSvg(name, size) {
|
|
7710
|
+
const s = Number(size) || 20;
|
|
7711
|
+
const body = STORE_ICONS[name] || STORE_ICONS.grid;
|
|
7712
|
+
const filled = name === 'paw';
|
|
7713
|
+
return `<svg viewBox="0 0 24 24" width="${s}" height="${s}" fill="${filled ? 'currentColor' : 'none'}" stroke="${filled ? 'none' : 'currentColor'}" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${body}</svg>`;
|
|
7714
|
+
}
|
|
7715
|
+
|
|
7679
7716
|
function storeCard(e, opts = {}) {
|
|
7680
|
-
const
|
|
7681
|
-
const
|
|
7717
|
+
const builtin = !!e.builtin;
|
|
7718
|
+
const installed = builtin || storeState.installed.has(e.id);
|
|
7719
|
+
const hasUpdate = !builtin && installed && e.updatedAt && e.installedAt && String(e.updatedAt) > String(e.installedAt);
|
|
7682
7720
|
const img = e.image
|
|
7683
7721
|
? `<span class="store-avatar"><img src="${e.image}" alt="" style="width:100%;height:100%;object-fit:cover;border-radius:8px"/></span>`
|
|
7684
|
-
: `<span class="store-avatar">${e.
|
|
7722
|
+
: `<span class="store-avatar store-avatar-ic">${storeIconSvg(e.icon, 20)}</span>`;
|
|
7685
7723
|
const author = e.author || {};
|
|
7686
|
-
const btnLabel = !installed ? _t('store_install') : hasUpdate ? _t('store_update') : _t('store_installed');
|
|
7724
|
+
const btnLabel = builtin ? _t('store_installed') : !installed ? _t('store_install') : hasUpdate ? _t('store_update') : _t('store_installed');
|
|
7687
7725
|
const btnDone = installed && !hasUpdate;
|
|
7688
7726
|
return `
|
|
7689
7727
|
<div class="store-card" data-id="${escapeHtml(e.id)}">
|
|
7690
7728
|
<div class="store-card-top">
|
|
7691
7729
|
${img}
|
|
7692
7730
|
<div style="min-width:0;flex:1">
|
|
7693
|
-
<div class="store-name" title="${escapeHtml(e.name)}">${escapeHtml(e.name)} <span class="store-ver">v${escapeHtml(e.version || '1.0.0')}</span
|
|
7731
|
+
<div class="store-name" title="${escapeHtml(e.name)}">${escapeHtml(e.name)} <span class="store-ver">v${escapeHtml(e.version || '1.0.0')}</span>${builtin ? ` <span class="store-builtin">${_t('store_builtin')}</span>` : ''}</div>
|
|
7694
7732
|
<div class="store-author">
|
|
7695
|
-
<span class="sa-avatar">${author.avatar ? escapeHtml(author.avatar) : '
|
|
7696
|
-
<span class="sa-name">${escapeHtml(author.username || '—')}</span>
|
|
7697
|
-
${author.beastId ? `<span class="sa-beast">${escapeHtml(author.beastId)}</span>` : ''}
|
|
7733
|
+
<span class="sa-avatar">${builtin ? storeIconSvg('paw', 13) : (author.avatar ? escapeHtml(author.avatar) : storeIconSvg('user', 13))}</span>
|
|
7734
|
+
<span class="sa-name">${escapeHtml(builtin ? 'beast' : (author.username || '—'))}</span>
|
|
7735
|
+
${!builtin && author.beastId ? `<span class="sa-beast">${escapeHtml(author.beastId)}</span>` : ''}
|
|
7698
7736
|
</div>
|
|
7699
7737
|
</div>
|
|
7700
7738
|
</div>
|
|
7701
7739
|
<div class="store-desc">${escapeHtml(e.description || '')}</div>
|
|
7702
7740
|
${(e.tags || []).length ? `<div class="store-tags">${e.tags.map((t) => `<span class="store-tag">${escapeHtml(t)}</span>`).join('')}</div>` : ''}
|
|
7703
7741
|
<div class="store-card-foot">
|
|
7704
|
-
|
|
7705
|
-
|
|
7742
|
+
${builtin
|
|
7743
|
+
? `<span class="store-stats"><span>${storeIconSvg('box', 13)} ${_t('store_builtin_note')}</span></span>`
|
|
7744
|
+
: `<span class="store-stats"><span>${storeIconSvg('download', 13)} ${e.installs || 0} ${_t('store_installs')}</span><span>${storeIconSvg('heart', 13)} ${e.likes || 0} ${_t('store_likes')}</span></span>
|
|
7745
|
+
<button class="store-like ${e.liked ? 'liked' : ''}" data-like="${escapeHtml(e.id)}">${storeIconSvg('heart', 14)}</button>`}
|
|
7706
7746
|
<button class="store-install ${btnDone ? 'done' : ''}" data-install="${escapeHtml(e.id)}">${btnLabel}</button>
|
|
7707
7747
|
</div>
|
|
7708
7748
|
</div>`;
|
|
@@ -7711,6 +7751,7 @@ function storeCard(e, opts = {}) {
|
|
|
7711
7751
|
function bindStoreCardActions(pane) {
|
|
7712
7752
|
pane.querySelectorAll('[data-install]').forEach((btn) =>
|
|
7713
7753
|
btn.addEventListener('click', async () => {
|
|
7754
|
+
if (btn.classList.contains('done')) return; /* kurulu/yerleşik — tıklama yok */
|
|
7714
7755
|
const id = btn.dataset.install;
|
|
7715
7756
|
btn.disabled = true;
|
|
7716
7757
|
const r = await beast.storeInstall(id).catch(() => null);
|
|
@@ -7739,7 +7780,7 @@ function bindStoreCardActions(pane) {
|
|
|
7739
7780
|
function renderStoreList(mode) {
|
|
7740
7781
|
const pane = $('#storePane');
|
|
7741
7782
|
const list = storeState.entries
|
|
7742
|
-
.filter((e) => (mode === 'stars' ? storeAgeDays(e.createdAt) >= 14 && storeStarsScore(e) > 0 : true))
|
|
7783
|
+
.filter((e) => (mode === 'stars' ? (e.builtin || (storeAgeDays(e.createdAt) >= 14 && storeStarsScore(e) > 0)) : true))
|
|
7743
7784
|
.sort((a, b) => (mode === 'stars' ? storeStarsScore(b) - storeStarsScore(a) : storeTrendingScore(b) - storeTrendingScore(a)))
|
|
7744
7785
|
.slice(0, 30);
|
|
7745
7786
|
pane.innerHTML =
|
|
@@ -7957,8 +7998,7 @@ function renderStoreUpload() {
|
|
|
7957
7998
|
}
|
|
7958
7999
|
|
|
7959
8000
|
function renderStorePane() {
|
|
7960
|
-
|
|
7961
|
-
else renderStoreList(storeState.tab);
|
|
8001
|
+
renderStoreList(storeState.tab);
|
|
7962
8002
|
const bid = $('#storeBeastId');
|
|
7963
8003
|
if (bid) bid.textContent = storeState.beastId || '';
|
|
7964
8004
|
}
|
package/src/renderer/style.css
CHANGED
|
@@ -3852,6 +3852,22 @@ body.browser-open #storeOverlay { right: var(--bw, 480px); }
|
|
|
3852
3852
|
}
|
|
3853
3853
|
.store-name { font-weight: 700; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3854
3854
|
.store-ver { font-size: 10.5px; color: var(--muted); }
|
|
3855
|
+
.store-builtin {
|
|
3856
|
+
font-size: 9.5px;
|
|
3857
|
+
font-weight: 700;
|
|
3858
|
+
letter-spacing: 0.5px;
|
|
3859
|
+
color: var(--muted);
|
|
3860
|
+
border: 1px solid var(--border);
|
|
3861
|
+
border-radius: 20px;
|
|
3862
|
+
padding: 1px 7px;
|
|
3863
|
+
background: var(--panel2);
|
|
3864
|
+
vertical-align: 1px;
|
|
3865
|
+
}
|
|
3866
|
+
.store-avatar-ic { color: var(--text); }
|
|
3867
|
+
.store-avatar-ic svg { display: block; }
|
|
3868
|
+
.store-author .sa-avatar svg { display: inline-block; vertical-align: -2px; }
|
|
3869
|
+
.store-stats svg { vertical-align: -2px; }
|
|
3870
|
+
.store-like svg { display: block; }
|
|
3855
3871
|
.store-author { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); min-width: 0; }
|
|
3856
3872
|
.store-author .sa-avatar { font-size: 13px; }
|
|
3857
3873
|
.store-author .sa-name { font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|