### README (README.md)
|
|
|
` render, sub/superscript → unicode, HTML entities decoded.",
"Collapsible `` render as tap-to-expand cards. Badge / button image rows flow inline.",
"Manual matching trusts your version — no re-download to verify.",
"Section-aware sort across library — Installed, Starred, Favourites each remember their own choice."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Design overhaul — new Geist typography, hero app header on Details, redesigned Home cards with platform glyphs, Apple-style menus, and a refreshed Library with an updates banner and a 'Ready to install' section.",
"Tablet two-pane layout — Home, Search, and Library keep the list on the left and open the repo on the right; drag the divider to resize.",
"Inner Details pages — About and What's New now slide in as dedicated screens with their own back action, and stay inside the right pane on tablet.",
"Real Apple and Tux icons for the macOS and Linux platform indicators across cards and lists.",
"Desktop remembers your last window size, position, and maximized state across launches; new windows open centered instead of in the top-left corner.",
"Linking an installed app now also matches against your starred repos — 'Scan GitHub Apps' surfaces repos you've starred as suggestions automatically, so you rarely need to paste a URL."
]
},
{
"type": "FIXED",
"bullets": [
"Discovery cards now show every platform a repo ships installers for, not just the one whose endpoint listed it.",
"What's New tag row no longer wraps long release tags into a one-character-wide vertical date column.",
"Checksum mismatch when a mirror was active — fixed a race between mirror and direct downloads writing to the same destination file.",
"Windows 11 title bar now matches system dark mode instead of staying glaringly white.",
"Silent install via root now properly triggers the Magisk / KernelSU permission prompt on Android 14+ instead of immediately reporting 'No root'; the root path was rewritten on top of libsu.",
"Linking an installed app to a GitHub repo now immediately shows 'Update to X' when the installed version is older, instead of misleading 'Install vX' until the next update check.",
"Desktop side drawer now shows the actual Komi Store logo instead of a 'G' placeholder.",
"Desktop content width (Home, Details, Auth) now scales as a fraction of the window — Compact / Wide / Extra wide adapt to monitor size instead of being capped to fixed pixel widths.",
"Linux desktop no longer crashes on launch on glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — the AppImage, deb, rpm, and Arch builds now bypass the broken bundled launcher and start the JVM directly."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Browse a repository's Issues without leaving the app — filter open or closed, see labels at a glance, and open full issue threads with comments, images, and Markdown.",
"New per-repository Security page — published security advisories with severity badges, plus the project's SECURITY.md policy rendered inline.",
"Sign in to interact directly — star a repo, comment on issues, open new issues, and react with 👍.",
"Browse a repository's Pull requests with open and closed filters.",
"Android home-screen shortcuts — long-press the app icon to jump straight to Search, your Library, Favourites, or Recently Viewed, and drag any of them out as a standalone launcher icon.",
"Import any GitHub user's starred repositories straight into your favourites — no sign-in needed. Open Favourites, tap the new person-plus icon, type a username, and add the repos you want.",
"You can now select and copy a repository's name, description, and stats on its detail page — long-press the text to copy it and look it up elsewhere.",
"Windows: a portable version is now available — unzip it and run Komi-Store.exe directly, with no installation needed.",
"Desktop: a richer top menu bar — new File and Go menus let you jump to Home, Search, Library, Favourites, or Recently Viewed, open settings, or quit, straight from the menu."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 can now install the .deb again — the package no longer demands the time64 'libasound2t64' / 'libpng16-16t64' libraries that only exist on Debian 13+, so a single .deb installs across every Debian generation.",
"Desktop sign-in no longer gets stuck on “Waiting for authorization…” — if the browser hand-off doesn't come back, it now times out so you can retry or switch to a device code or token.",
"Windows: “Open in Komi Store” links now reliably open the app — the githubstore:// handler is registered more robustly and re-registered after updates, so links no longer fail with “no application associated”.",
"macOS: the app no longer quits unexpectedly when you open your Profile or switch between windows."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"New Explore tab — a fresh discovery feed of installable apps for your platform. It refreshes daily so there's always something new, and loads more as you scroll.",
"New Top Charts tab — see what's trending, just released, and most popular, ranked across the whole store."
]
},
{
"type": "FIXED",
"bullets": [
"App downloads now auto-pick the build that matches your device's CPU (like aarch64) instead of defaulting to a larger universal APK.",
"Fixed GitHub sign-in on Windows — the desktop app now reliably opens and finishes login after you authorize in your browser.",
"Fixed the app not launching from the menu on some Linux setups (like Arch/KDE) caused by a mismatched desktop-shortcut name."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/22.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/22.json)
{
"versionCode": 22,
"versionName": "1.9.3",
"releaseDate": "2026-06-28",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Traditional Chinese (繁體中文) is now available — switch to it anytime under Tweaks → Language."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ar/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ar/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect: ألقِ نظرة داخل أي إصدار قبل تثبيته.",
"تثبيت صامت عبر Dhizuku: تجاوز نوافذ التثبيت في أجهزة Xiaomi و OPPO و vivo و Huawei عبر صلاحية «مالك الجهاز».",
"استيراد/تصدير Obtainium: انقل مكتبتك من Obtainium بنقرة واحدة، أو صدّر إلى صيغة Obtainium في أي وقت.",
"إضافة من المُنجَّمة: استعرض المستودعات التي تشحن APK ضمن نجوم GitHub لديك."
]
},
{
"type": "IMPROVED",
"bullets": [
"عدّاد المشكلات المفتوحة والترخيص يظهران الآن للجميع بمن فيهم غير المسجَّلين — يأتيان من الخادم الخلفي دون أي تكلفة لحصص GitHub.",
"يمكنك إيقاف التحقق التلقائي من التحديثات في الخلفية بالكامل — يوفّر البطارية إذا كنت تفضّل التحقق يدوياً."
]
},
{
"type": "FIXED",
"bullets": [
"تمت إزالة تأثير الزجاج السائل — قد تختفي الأيقونات في الوضع الداكن على الخلفيات الشفافة. واجهة أنظف بتباين أعلى في كل مكان."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ar/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ar/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"تجاهل التحديثات لكل تطبيق — أوقف تنبيه التحديث لأي تطبيق لا ترغب في تحديثه.",
"تخطّي إصدار محدد — تجاهل تنبيه تحديث واحد إذا كان خاطئًا، وسيتم إعلامك حين يصدر إصدار أحدث.",
"تثبيت صامت عبر روت — يمكن لمستخدمي Magisk و KernelSU و APatch التثبيت الآن دون Shizuku أو Dhizuku."
]
},
{
"type": "FIXED",
"bullets": [
"التطبيقات التي تم إلغاء تثبيتها — حتى من إعدادات النظام — تختفي الآن فوراً من قائمة التطبيقات المتتبَّعة.",
"اكتشاف أدق للإصدارات — لم يعد المتجر يعتبر الإصدارات التي تحمل نفس الأرقام لكن بيانات بناء مختلفة 'مثبَّتة بالفعل'.",
"تحديث عدة تطبيقات بالتتابع أصبح موثوقاً — التثبيتات تنتظر بعضها فلا يظهر مربع حوار النظام تطبيقاً سابقاً، كما تتحدث الإصدارات في شاشة التطبيقات بشكل صحيح بعد كل تثبيت.",
"يختار التحديث التلقائي حزمة APK الصحيحة عندما تشحن النسخة كلا من النسختين العادية و F-Droid — لا مزيد من التثبيت العرضي لتطبيق شقيق بمعرّف حزمة مختلف."
]
},
{
"type": "IMPROVED",
"bullets": [
"تحديثات خلفية أكثر موثوقية على Oppo و OnePlus و Realme و Xiaomi و vivo و Honor — توفّر الإعدادات الآن اختصاراً بنقرة واحدة لاستثناء البطارية، وتعمل مهام التحديث بأولوية مُعجَّلة.",
"تثبيت صامت Dhizuku على Android 14+ — يعيد التطبيق المحاولة تلقائيًا بدون نسبة المثبِّت عندما يطلب النظام تأكيدًا."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ar/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ar/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"دعم Codeberg + Forgejo + Gitea. الصق رابط Codeberg / Forgejo أو أضف مضيفك الخاص من الإعدادات → الشبكة. التفاصيل، التثبيت، التحديثات، البحث — كلها متصلة.",
"تثبيت macOS عبر Homebrew: `brew install --cask github-store`.",
"تسجيل الدخول إلى GitHub يستخدم تدفق الويب القياسي — بدون رمز 8 أرقام.",
"التفضيلات والاعتمادات مشفّرة AES-256-GCM عبر KSafe (Keystore عتادي على Android). انتقال عند أول إقلاع.",
"إضافة مرآة fastly.jsdelivr.net لـ GitHub المقيّد.",
"انضممنا إلى تحالف Keep Android Open — لافتة توضح."
]
},
{
"type": "FIXED",
"bullets": [
"شارات المنصة في التفاصيل تفتح Search مع فلتر (كانت بدون تأثير).",
"زر البحث في لوحة المفاتيح يعمل على Android 12 مع محررات الإدخال الصينية.",
"المستودع المرتبط خارجياً يعرض لافتة في التفاصيل مع زر فك ارتباط بنقرة واحدة.",
"تسجيل الدخول يفتح رابط الرمز مع تعبئة مسبقة + ينسخ نسخة مناسبة للصق.",
"تعطل Android 16 / ROMات مخصصة في الإعدادات + التنزيل — يستخدم التخزين الداخلي.",
"اكتشاف Magisk / KernelSU / APatch على Android 13+ (فحص محجوب بـ SELinux).",
"تسمية المتغير المثبت تتحدث — بدون أرقام beta/rc قديمة.",
"README / ملاحظات الإصدار تحتفظ بموضع التمرير عبر إعادة إنشاء العرض."
]
},
{
"type": "IMPROVED",
"bullets": [
"ورقة الربط اليدوي مرتبة حسب مصدر التثبيت (F-Droid / Obtainium أولاً، تحديثات النظام أخيراً) مع شارة مصدر لكل تطبيق.",
"Smart match يقترح مستودعات مرتبة من GitHub + Codeberg + منصّات مخصّصة.",
"تنبيهات GFM (Note / Tip / Important / Warning / Caution) كبطاقات ملونة.",
"اختصارات الإيموجي — :rocket: → 🚀 (~250 مغطاة).",
"صور SVG تُعرض أصلياً. الصور المخصصة لسمة تحترم الفاتح/الداكن. UA المتصفح يفك حجب شارات CDN.",
"كتل الكود ملونة (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell، متجاوبة مع السمة).",
"تحسينات Markdown — اقتباسات HTML و`` تظهر، النصوص العلوية/السفلية → Unicode، كيانات HTML مُفكّكة الترميز.",
"أقسام `` القابلة للطي كبطاقات قابلة للتوسيع بنقرة. صفوف صور الشارات/الأزرار تتدفق في سطر واحد.",
"المطابقة اليدوية تعتمد إصدارك المختار — بدون إعادة تنزيل للتحقق.",
"فرز خاص بكل قسم — المثبّتة، المميَّزة بنجمة، المفضلة تحفظ اختيارها."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Bn/15.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/bn/15.json)
{
"versionCode": 15,
"versionName": "1.8.0",
"releaseDate": "2026-05-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Komi Store-এর নিজস্ব ব্যাকএন্ড: সাইন-ইন, সার্চ আর ডিসকভারি এখন চীনেও কাজ করে।",
"লাইব্রেরি ইম্পোর্ট: ডিভাইসে আগে থেকেই ইনস্টল থাকা GitHub অ্যাপগুলো আপনাআপনি শনাক্ত হয়।",
"ডাউনলোড মিরর সিস্টেম: একাধিক উৎসের রেস আর SHA-256 যাচাই একসাথে।",
"যেসব নেটওয়ার্কে ব্রাউজার-ভিত্তিক OAuth ব্লক, সেখানে Personal Access Token দিয়ে সাইন-ইন।"
]
},
{
"type": "IMPROVED",
"bullets": [
"অ্যাপের ভেতর থেকে ফিডব্যাক পাঠান: বাগ রিপোর্ট, ফিচার আইডিয়া, পরিবর্তনের অনুরোধ।",
"প্রি-রিলিজ চ্যানেল চিপ এবং Details স্ক্রিনে 'স্টেবল-এ ফিরুন' বোতাম।",
"Arch Linux-এর জন্য নেটিভ pkg.tar.zst প্যাকেজ, পাশাপাশি deb, rpm আর AppImage।"
]
},
{
"type": "FIXED",
"bullets": [
"Linux Desktop পুনরায় চালু হলে আর নীরবে সেটিংস ও লাইব্রেরি মুছে ফেলে না।",
"নির্বাচিত ভ্যারিয়েন্টকে সম্মান: ওভাররাইট ছাড়াই বেছে নেওয়া ভ্যারিয়েন্ট ইনস্টল হয়।",
"Compose Multiplatform 1.10.3 আপডেটের মাধ্যমে macOS-এর অ্যাক্সেসিবিলিটি ক্র্যাশ ঠিক করা হয়েছে।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Bn/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/bn/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"প্রতিটি অ্যাপের আপডেট উপেক্ষা করুন — যে অ্যাপটি আপডেট করতে চান না, তার আপডেট ব্যাজ বন্ধ করে দিন।",
"নির্দিষ্ট আপডেট এড়িয়ে যান — কোনো ভুল আপডেট প্রম্পট হলে এড়িয়ে যান; নতুন সংস্করণ এলে আবার সূচিত করা হবে।",
"Root দিয়ে নীরব ইনস্টল — Magisk, KernelSU ও APatch ব্যবহারকারীরা এখন Shizuku বা Dhizuku ছাড়াই ইনস্টল করতে পারবেন।"
]
},
{
"type": "FIXED",
"bullets": [
"সিস্টেম সেটিংস থেকে আনইনস্টল করা অ্যাপগুলো এখন ট্র্যাক করা তালিকা থেকে তাৎক্ষণিকভাবে সরে যায়।",
"আরও সঠিক সংস্করণ শনাক্তকরণ — একই সংখ্যা থাকলেও আলাদা বিল্ডের রিলিজগুলো এখন ভুল করে 'ইতিমধ্যে ইনস্টল করা' হিসেবে দেখানো হয় না।",
"একসাথে কয়েকটি অ্যাপ আপডেট এখন নির্ভরযোগ্য — ইনস্টলগুলো ক্রমান্বয়ে চলে, তাই সিস্টেম ডায়ালগ আগের APK দেখায় না। প্রতিটি ইনস্টলের পর অ্যাপস স্ক্রিনে সংস্করণও সঠিকভাবে আপডেট হয়।",
"যখন কোনো রিলিজে সাধারণ ও F-Droid দুই ভ্যারিয়েন্ট থাকে, স্বয়ংক্রিয় আপডেট এখন সঠিক APK বেছে নেয় — অন্য প্যাকেজ আইডির আরেকটি অ্যাপ ভুলবশত ইনস্টল হবে না।"
]
},
{
"type": "IMPROVED",
"bullets": [
"Oppo, OnePlus, Realme, Xiaomi, vivo এবং Honor-এ আরও নির্ভরযোগ্য ব্যাকগ্রাউন্ড আপডেট — সেটিংস এখন এক-ট্যাপে ব্যাটারি অপটিমাইজেশনের শর্টকাট দেয় এবং আপডেট ওয়ার্কারগুলো ত্বরান্বিত অগ্রাধিকারে চলে।",
"Android 14+ এ Dhizuku নীরব ইনস্টল — সিস্টেম নিশ্চিতকরণ চাইলে অ্যাপ স্বয়ংক্রিয়ভাবে ইনস্টলার অ্যাট্রিবিউশন ছাড়া আবার চেষ্টা করে।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Bn/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/bn/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Codeberg + Forgejo + Gitea সমর্থন। Codeberg / Forgejo URL পেস্ট করুন বা Tweaks → নেটওয়ার্কে আপনার সেলফ-হোস্টেড হোস্ট যোগ করুন। বিস্তারিত, ইনস্টল, আপডেট, সার্চ — সবই সংযুক্ত।",
"Homebrew দিয়ে macOS ইনস্টল: `brew install --cask github-store`।",
"GitHub সাইন-ইন স্ট্যান্ডার্ড ওয়েব ফ্লো — 8-সংখ্যার কোড লাগে না।",
"পছন্দ ও ক্রেডেনশিয়াল KSafe-এর মাধ্যমে AES-256-GCM এনক্রিপ্টেড (Android-এ হার্ডওয়্যার Keystore)। প্রথম চালুতে মাইগ্রেশন।",
"সীমিত GitHub-এর জন্য fastly.jsdelivr.net মিরর যোগ।",
"Keep Android Open কোয়ালিশনে যোগ — ব্যানার ব্যাখ্যা করে।"
]
},
{
"type": "FIXED",
"bullets": [
"বিস্তারিতে প্ল্যাটফর্ম চিপ ফিল্টার করা Search খোলে (আগে নিষ্ক্রিয় ছিল)।",
"Android 12-এ কিবোর্ড সার্চ বোতাম চীনা IME-তে কাজ করে।",
"বাহ্যিকভাবে লিঙ্ক করা রিপো বিস্তারিতে এক-ট্যাপ আনলিঙ্ক ব্যানার দেখায়।",
"সাইন-ইন কোড URL আগে থেকে পূরণ করে খোলে + পেস্ট-বান্ধব কোড কপি করে।",
"Android 16 / কাস্টম ROM-এ সেটিংস + ডাউনলোড ক্র্যাশ — অভ্যন্তরীণ স্টোরেজে ফলব্যাক।",
"Android 13+-এ Magisk / KernelSU / APatch শনাক্তকরণ (SELinux-এ ঢাকা পড়া যাচাই)।",
"পিনড ভ্যারিয়েন্ট লেবেল রিফ্রেশ হয় — পুরোনো beta/rc নম্বর নেই।",
"README / রিলিজ নোট ভিউপোর্ট ডিসপোজাল জুড়ে স্ক্রল অবস্থান ধরে রাখে।"
]
},
{
"type": "IMPROVED",
"bullets": [
"ম্যানুয়াল লিঙ্ক শিট ইনস্টলার উৎস অনুযায়ী সাজানো (F-Droid / Obtainium প্রথমে, সিস্টেম আপডেট শেষে), অ্যাপ অনুযায়ী উৎস চিপ।",
"Smart match GitHub + Codeberg + কাস্টম ফোর্জ থেকে র্যাংকড রিপো সাজেস্ট করে।",
"GFM অ্যালার্ট (Note / Tip / Important / Warning / Caution) রঙিন কার্ড হিসেবে।",
"ইমোজি শর্টকোড — :rocket: → 🚀 (~250 কভার)।",
"SVG ছবি নেটিভভাবে রেন্ডার। থিম-নির্দিষ্ট ছবি লাইট/ডার্ক মেনে চলে। ব্রাউজার UA CDN ব্যাজ আনব্লক করে।",
"কোড ব্লকে সিনট্যাক্স হাইলাইটিং (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, থিম-সচেতন)।",
"Markdown উন্নতি — HTML blockquote ও `` রেন্ডার, sub/superscript → unicode, HTML entities ডিকোড।",
"ভাঁজযোগ্য `` সেকশন ট্যাপ-টু-এক্সপ্যান্ড কার্ড। ব্যাজ/বোতাম ছবির সারি এক লাইনে।",
"ম্যানুয়াল ম্যাচিং আপনার বেছে নেওয়া সংস্করণ ট্রাস্ট করে — যাচাইয়ের জন্য পুনঃডাউনলোড নেই।",
"সেকশন-নির্ভর সর্ট — ইনস্টলড, স্টারড, প্রিয় নিজস্ব পছন্দ মনে রাখে।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Bn/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/bn/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"ডিজাইন ওভারহল — নতুন Geist টাইপোগ্রাফি, Details-এ হিরো হেডার, প্ল্যাটফর্ম গ্লিফসহ পুনঃডিজাইন করা Home কার্ড, Apple-স্টাইল মেনু, এবং আপডেট ব্যানার ও 'ইনস্টলের জন্য প্রস্তুত' সেকশনসহ রিফ্রেশড লাইব্রেরি।",
"ট্যাবলেট টু-প্যান লেআউট — Home, Search এবং লাইব্রেরি তালিকাকে বাঁ পাশে রাখে এবং রিপোকে ডান পাশে খোলে; আকার পরিবর্তনের জন্য বিভাজক টানুন।",
"অভ্যন্তরীণ Details পৃষ্ঠা — About এবং What's New এখন তাদের নিজস্ব ব্যাক অ্যাকশনসহ ডেডিকেটেড স্ক্রিন হিসেবে স্লাইড ইন হয়, এবং ট্যাবলেটে ডান প্যানের ভিতরে থাকে।",
"কার্ড এবং তালিকা জুড়ে macOS এবং Linux প্ল্যাটফর্ম ইন্ডিকেটরের জন্য আসল Apple এবং Tux আইকন।",
"ডেস্কটপ লঞ্চের মধ্যে আপনার শেষ উইন্ডো সাইজ, অবস্থান এবং ম্যাক্সিমাইজড স্টেট মনে রাখে; নতুন উইন্ডো উপরের-বাম কোণার পরিবর্তে কেন্দ্রে খোলে।",
"ইনস্টল করা অ্যাপ লিঙ্ক করা এখন আপনার স্টার করা রিপোগুলির সাথেও মেলে — 'GitHub অ্যাপ স্ক্যান' আপনার স্টার করা রিপোগুলি স্বয়ংক্রিয়ভাবে সাজেশন হিসেবে দেখায়, তাই আপনাকে খুব কমই URL পেস্ট করতে হয়।"
]
},
{
"type": "FIXED",
"bullets": [
"Discovery কার্ড এখন প্রতিটি প্ল্যাটফর্ম দেখায় যেগুলির জন্য রিপো ইনস্টলার পাঠায়, শুধুমাত্র এন্ডপয়েন্ট যেগুলি তালিকাবদ্ধ করেছে তাই নয়।",
"What's New ট্যাগ সারি এখন আর দীর্ঘ রিলিজ ট্যাগগুলিকে এক-অক্ষর-প্রশস্ত উল্লম্ব তারিখ কলামে মোড়ায় না।",
"মিরর সক্রিয় থাকাকালে চেকসাম মিসম্যাচ — মিরর এবং ডাইরেক্ট ডাউনলোডের মধ্যে একই গন্তব্য ফাইলে লেখার রেস কন্ডিশন ঠিক করা হয়েছে।",
"Windows 11 টাইটেল বার এখন উজ্জ্বল সাদা থাকার পরিবর্তে সিস্টেম ডার্ক মোডের সাথে মেলে।",
"root দিয়ে সাইলেন্ট ইনস্টল এখন Android 14+-এ অবিলম্বে 'No root' রিপোর্ট করার পরিবর্তে Magisk / KernelSU অনুমতি প্রম্পট সঠিকভাবে ট্রিগার করে; root পাথ libsu-এর উপর পুনর্লিখিত হয়েছে।",
"ইনস্টল করা অ্যাপকে GitHub রিপোতে লিঙ্ক করা এখন অবিলম্বে 'Update to X' দেখায় যখন ইনস্টল করা সংস্করণ পুরানো, পরবর্তী আপডেট চেক পর্যন্ত বিভ্রান্তিকর 'Install vX'-এর পরিবর্তে।",
"ডেস্কটপ সাইড ড্রয়ার এখন 'G' প্লেসহোল্ডারের পরিবর্তে আসল Komi Store লোগো দেখায়।",
"ডেস্কটপ কন্টেন্ট প্রস্থ (Home, Details, Auth) এখন উইন্ডোর ভগ্নাংশ হিসেবে স্কেল হয় — কম্প্যাক্ট / ওয়াইড / এক্সট্রা ওয়াইড স্থির পিক্সেল প্রস্থে সীমাবদ্ধ থাকার পরিবর্তে মনিটর সাইজের সাথে মানিয়ে নেয়।",
"Linux ডেস্কটপ এখন glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite)-এ লঞ্চের সময় আর ক্র্যাশ করে না — AppImage, deb, rpm এবং Arch বিল্ড এখন ত্রুটিপূর্ণ বান্ডিল লঞ্চার বাইপাস করে সরাসরি JVM শুরু করে।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/15.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/15.json)
{
"versionCode": 15,
"versionName": "1.8.0",
"releaseDate": "2026-05-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Backend de Komi Store: autenticación, búsqueda y descubrimiento funcionan en China.",
"Importación de biblioteca: detecta automáticamente las apps de GitHub que ya tienes instaladas.",
"Sistema de mirrors de descarga: carrera multi-origen con verificación SHA-256.",
"Inicio de sesión con Personal Access Token para redes que bloquean el flujo OAuth en navegador."
]
},
{
"type": "IMPROVED",
"bullets": [
"Envía comentarios desde la app: reportes de errores, ideas y solicitudes de cambio.",
"Selector de canal pre-release y opción «volver a estable» en Detalles.",
"Paquetes nativos pkg.tar.zst para Arch Linux, junto a deb, rpm y AppImage."
]
},
{
"type": "FIXED",
"bullets": [
"Linux Desktop ya no borra silenciosamente la configuración y la biblioteca al reiniciar.",
"Selección de variante respetada: la variante elegida se instala sin sobrescritura.",
"Solucionado el bloqueo de accesibilidad en macOS gracias a Compose Multiplatform 1.10.3."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect: examina el contenido de cualquier release antes de instalarlo.",
"Instalación silenciosa con Dhizuku: omite los diálogos de instalación de OEM en Xiaomi, OPPO, vivo y Huawei mediante el propietario del dispositivo.",
"Importar/Exportar Obtainium: trae tu biblioteca desde Obtainium con un toque, o exporta a formato Obtainium cuando quieras.",
"Añadir desde estrellas: descubre los repos de tus estrellas en GitHub que envían APK."
]
},
{
"type": "IMPROVED",
"bullets": [
"El número de incidencias abiertas y la licencia ahora se muestran a todos, incluidos los usuarios sin sesión — vienen del backend, sin coste de cuota de GitHub.",
"La comprobación de actualizaciones en segundo plano se puede desactivar por completo — ahorra batería si prefieres comprobar manualmente."
]
},
{
"type": "FIXED",
"bullets": [
"Efecto de cristal líquido eliminado — los iconos en modo oscuro podían volverse invisibles sobre fondos transparentes. Interfaz más limpia y con mayor contraste en todas partes."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Ignorar actualizaciones por app — silencia la insignia de actualización en cualquier app que no quieras actualizar.",
"Saltar una actualización concreta — descarta un aviso si es un falso positivo; recibirás un nuevo aviso cuando salga otra versión.",
"Instalación silenciosa por root — usuarios de Magisk, KernelSU y APatch pueden instalar sin Shizuku o Dhizuku."
]
},
{
"type": "FIXED",
"bullets": [
"Las apps desinstaladas desde Ajustes del sistema ahora desaparecen al instante de la lista de seguimiento.",
"Mejor detección de versiones — las releases que comparten número pero llevan metadatos de build distintos ya no se marcan por error como 'ya instaladas'.",
"Actualizar varias apps seguidas ahora funciona bien — las instalaciones se serializan para que cada diálogo del sistema muestre el APK correcto. Las versiones en la pantalla de apps también se mantienen al día tras cada instalación.",
"La actualización automática elige el APK correcto cuando una release incluye tanto la variante normal como la de F-Droid — adiós a instalar por accidente una app hermana con otro ID de paquete."
]
},
{
"type": "IMPROVED",
"bullets": [
"Actualizaciones en segundo plano más fiables en Oppo, OnePlus, Realme, Xiaomi, vivo y Honor — Ajustes ofrece ahora un acceso directo a la exclusión de optimización de batería, y las comprobaciones de actualización se ejecutan con prioridad acelerada.",
"Instalación silenciosa Dhizuku en Android 14+ — la app reintenta automáticamente sin atribución de instalador cuando el sistema exigiría una confirmación."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Soporte para Codeberg + Forgejo + Gitea. Pega una URL de Codeberg / Forgejo o añade tu host self-hosted en Ajustes → Red. Detalles, instalación, actualizaciones, búsqueda — todo conectado.",
"Instalación en macOS con Homebrew: `brew install --cask github-store`.",
"Iniciar sesión con GitHub usa el flujo web estándar — sin código de 8 dígitos.",
"Preferencias y credenciales cifradas con AES-256-GCM vía KSafe (Keystore por hardware en Android). Migración al primer arranque.",
"Mirror fastly.jsdelivr.net para GitHub limitado.",
"Nos unimos a la coalición Keep Android Open — banner lo explica."
]
},
{
"type": "FIXED",
"bullets": [
"Chips de plataforma en Detalles abren Search filtrado (antes no hacían nada).",
"Botón de búsqueda del teclado funciona en Android 12 con IMEs chinos.",
"Repo enlazado externamente muestra banner en Detalles con un toque para desvincular.",
"Inicio de sesión abre URL del código prellenada y copia código compatible con pegado.",
"Crash en Android 16 / ROMs personalizadas en Ajustes + descargas — usa almacenamiento interno.",
"Detección de Magisk / KernelSU / APatch en Android 13+ (probe ocultado por SELinux).",
"Etiqueta de variante fijada se refresca — sin números beta/rc obsoletos.",
"README / notas de versión conservan posición de scroll entre desasignaciones de viewport."
]
},
{
"type": "IMPROVED",
"bullets": [
"Hoja de enlace manual ordena por origen del instalador (F-Droid / Obtainium primero, actualizaciones del sistema al final) con chip de origen por app.",
"Smart match sugiere repos clasificados de GitHub + Codeberg + forjas personalizadas.",
"Llamadas de alerta GFM (Note / Tip / Important / Warning / Caution) como tarjetas tintadas.",
"Atajos de emoji — :rocket: → 🚀 (~250 cubiertos).",
"Imágenes SVG renderizan nativamente. Imágenes con tema respetan claro/oscuro. UA de navegador desbloquea badges de CDN.",
"Bloques de código con resaltado (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, adaptado al tema).",
"Pulido de Markdown — blockquotes HTML y `` renderizan, sub/superíndice → unicode, entidades HTML decodificadas.",
"Secciones `` colapsables como tarjetas tap-to-expand. Filas de imágenes badge/botón fluyen en línea.",
"Vinculación manual confía en tu versión — sin re-descarga para verificar.",
"Orden por sección — Instaladas, Con estrella, Favoritos recuerdan su propia elección."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Renovación de diseño — nueva tipografía Geist, hero header en Detalles, tarjetas de Home rediseñadas con glifos de plataforma, menús estilo Apple y Biblioteca renovada con banner de actualizaciones y sección 'Listo para instalar'.",
"Diseño de dos paneles en tablet — Home, Búsqueda y Biblioteca mantienen la lista a la izquierda y abren el repo a la derecha; arrastra el divisor para ajustar.",
"Páginas internas de Detalles — Acerca de y Novedades aparecen como pantallas dedicadas con su propia acción de retroceso, y se quedan en el panel derecho en tablet.",
"Iconos reales de Apple y Tux para los indicadores de macOS y Linux en tarjetas y listas.",
"El escritorio recuerda el tamaño, posición y estado maximizado de la ventana entre lanzamientos; las ventanas nuevas se abren centradas en lugar de en la esquina superior izquierda.",
"Vincular una app instalada ahora también busca en tus repos con estrella — 'Escanear apps de GitHub' sugiere automáticamente los repos que has marcado con estrella, así rara vez necesitas pegar una URL."
]
},
{
"type": "FIXED",
"bullets": [
"Las tarjetas de descubrimiento muestran ahora todas las plataformas con instaladores, no solo la del endpoint que la listó.",
"La fila de etiquetas de Novedades ya no envuelve las etiquetas largas en una columna de fecha vertical de un carácter de ancho.",
"Discrepancia de checksum con un mirror activo — corregida la condición de carrera entre descargas mirror y directa al mismo archivo destino.",
"La barra de título de Windows 11 ahora coincide con el modo oscuro del sistema en lugar de quedarse blanca.",
"La instalación silenciosa con root ahora dispara correctamente el prompt de permisos de Magisk / KernelSU en Android 14+ en vez de reportar 'Sin root' al instante; el camino de root fue reescrito sobre libsu.",
"Vincular una app instalada a un repo de GitHub muestra inmediatamente 'Actualizar a X' cuando la versión instalada es más antigua, en lugar del engañoso 'Instalar vX' hasta la siguiente comprobación de actualizaciones.",
"El cajón lateral del escritorio ahora muestra el logo real de Komi Store en lugar del placeholder 'G'.",
"El ancho de contenido en escritorio (Home, Detalles, Auth) ahora se escala como fracción de la ventana — Compacto / Ancho / Extra ancho se adaptan al tamaño del monitor en vez de estar limitados a anchos fijos en píxeles.",
"El escritorio Linux ya no se bloquea al iniciar en glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — AppImage, deb, rpm y Arch ahora omiten el lanzador empaquetado defectuoso e inician la JVM directamente."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Explora los Issues de un repositorio sin salir de la app — filtra por abiertos o cerrados, ve las etiquetas de un vistazo y abre hilos completos con comentarios, imágenes y Markdown.",
"Nueva página de Seguridad por repositorio — avisos de seguridad publicados con distintivos de gravedad, además de la política SECURITY.md del proyecto renderizada en línea.",
"Inicia sesión para interactuar directamente — marca un repo con estrella, comenta en los issues, abre nuevos issues y reacciona con 👍.",
"Explora los Pull requests de un repositorio con filtros de abiertos y cerrados.",
"Accesos directos en la pantalla de inicio de Android — mantén pulsado el icono de la app para ir directo a Buscar, tu Biblioteca, Favoritos o Vistos recientemente, y arrastra cualquiera como un icono independiente.",
"Importa los repositorios destacados de cualquier usuario de GitHub directamente a tus favoritos — sin necesidad de iniciar sesión. Abre Favoritos, toca el nuevo icono de añadir persona, escribe un nombre de usuario y añade los repos que quieras.",
"Ahora puedes seleccionar y copiar el nombre, la descripción y las estadísticas de un repositorio en su página de detalles: mantén pulsado el texto para copiarlo y buscarlo en otro sitio.",
"Windows: ya hay una versión portátil — descomprímela y ejecuta Komi-Store.exe directamente, sin necesidad de instalar.",
"Escritorio: una barra de menú superior más completa — los nuevos menús Archivo e Ir te llevan a Inicio, Búsqueda, Biblioteca, Favoritos o Vistos recientemente, abren los ajustes o cierran la app, directamente desde el menú."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 ya pueden instalar el .deb de nuevo — el paquete ya no exige las bibliotecas time64 'libasound2t64' / 'libpng16-16t64', que solo existen en Debian 13+, así que un único .deb se instala en todas las generaciones de Debian.",
"El inicio de sesión en el escritorio ya no se queda bloqueado en «Esperando autorización…»: si el navegador no completa el proceso, ahora caduca para que puedas reintentarlo o usar un código de dispositivo o un token.",
"Windows: los enlaces «Abrir en Komi Store» ahora abren la app de forma fiable: el controlador githubstore:// se registra de manera más robusta y se vuelve a registrar tras las actualizaciones, por lo que ya no fallan con «no hay ninguna aplicación asociada».",
"macOS: la app ya no se cierra de forma inesperada al abrir tu perfil o cambiar entre ventanas."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Es/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/es/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Nueva pestaña Explorar — un feed de descubrimiento de apps instalables para tu plataforma. Se actualiza a diario para que siempre haya algo nuevo y carga más a medida que te desplazas.",
"Nueva pestaña Populares — descubre lo que es tendencia, lo recién lanzado y lo más popular, clasificado en toda la tienda."
]
},
{
"type": "FIXED",
"bullets": [
"Las descargas de apps ahora eligen automáticamente la versión que coincide con la CPU de tu dispositivo (como aarch64) en lugar de recurrir a un APK universal más grande.",
"Se corrigió el inicio de sesión con GitHub en Windows: la aplicación de escritorio ahora se abre y completa el inicio de sesión de forma fiable después de autorizar en el navegador."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect : examinez le contenu d’une release avant de l’installer.",
"Installation silencieuse via Dhizuku : contournez les fenêtres d’installation des OEM (Xiaomi, OPPO, vivo, Huawei) grâce au statut Propriétaire de l’appareil.",
"Import/Export Obtainium : récupérez votre bibliothèque depuis Obtainium en un toucher, ou exportez vers Obtainium quand vous voulez.",
"Ajouter depuis les étoiles : repérez parmi vos repos étoilés sur GitHub ceux qui livrent un APK."
]
},
{
"type": "IMPROVED",
"bullets": [
"Le nombre d’issues ouvertes et la licence s’affichent désormais pour tout le monde, y compris les utilisateurs déconnectés — fournis par le backend, sans coût de quota GitHub.",
"La vérification des mises à jour en arrière-plan peut être complètement désactivée — économise la batterie si vous préférez vérifier manuellement."
]
},
{
"type": "FIXED",
"bullets": [
"Effet verre liquide supprimé — les icônes en mode sombre pouvaient devenir invisibles sur des fonds transparents. Interface plus nette et plus contrastée partout."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Ignorer les mises à jour par appli — masque la pastille de mise à jour pour les applis que tu ne veux pas mettre à jour.",
"Ignorer une mise à jour précise — écarte un avis s'il s'agit d'un faux positif ; tu seras réinformé dès qu'une nouvelle version paraîtra.",
"Installation silencieuse via root — les utilisateurs de Magisk, KernelSU et APatch peuvent installer sans Shizuku ni Dhizuku."
]
},
{
"type": "FIXED",
"bullets": [
"Les applis désinstallées depuis les Paramètres système disparaissent maintenant immédiatement de la liste suivie.",
"Meilleure détection de version — les releases qui partagent le même numéro mais portent des métadonnées de build différentes ne sont plus signalées à tort comme 'déjà installées'.",
"Mettre à jour plusieurs applis à la suite fonctionne maintenant correctement — les installations se sérialisent pour que chaque boîte de dialogue système affiche le bon APK. Les versions dans l'écran des applis restent aussi à jour après chaque installation.",
"La mise à jour auto choisit le bon APK quand une release embarque à la fois une variante standard et F-Droid — fini d'installer par erreur une appli sœur avec un autre ID de paquet."
]
},
{
"type": "IMPROVED",
"bullets": [
"Mises à jour en arrière-plan plus fiables sur Oppo, OnePlus, Realme, Xiaomi, vivo et Honor — Réglages propose désormais un raccourci d'un seul geste pour l'exclusion de l'optimisation de la batterie, et les vérifications de mise à jour s'exécutent en priorité accélérée.",
"Installation silencieuse Dhizuku sur Android 14+ — l'app réessaie automatiquement sans attribution d'installateur quand le système exigerait une confirmation."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Support Codeberg + Forgejo + Gitea. Colle une URL de Codeberg / Forgejo ou ajoute ton hôte auto-hébergé sous Tweaks → Réseau. Détails, install, mises à jour, recherche — tout est câblé.",
"Installation macOS via Homebrew : `brew install --cask github-store`.",
"Connexion GitHub utilise le flux web standard — plus de code à 8 chiffres.",
"Préférences et identifiants chiffrés AES-256-GCM via KSafe (Keystore matériel sur Android). Migration au premier lancement.",
"Mirror fastly.jsdelivr.net ajouté pour GitHub limité.",
"Rejoint la coalition Keep Android Open — bannière l'explique."
]
},
{
"type": "FIXED",
"bullets": [
"Puces de plateforme dans Détails ouvrent Search filtré (étaient inactives).",
"Bouton de recherche du clavier fonctionne sur Android 12 avec IME chinois.",
"Dépôt lié externalement affiche bannière sur Détails avec un tap pour dissocier.",
"Connexion ouvre URL du code pré-remplie + copie code adapté au collage.",
"Crash Android 16 / ROMs personnalisées sur Paramètres + téléchargement — bascule vers stockage interne.",
"Détection Magisk / KernelSU / APatch sur Android 13+ (sonde masquée par SELinux).",
"Étiquette de variante épinglée se rafraîchit — plus de numéros beta/rc obsolètes.",
"README / notes de version conservent la position de scroll au-delà des disposals de viewport."
]
},
{
"type": "IMPROVED",
"bullets": [
"Feuille de lien manuel triée par source d'installation (F-Droid / Obtainium d'abord, mises à jour système en dernier) avec chip de source par app.",
"Smart match suggère des dépôts classés sur GitHub + Codeberg + forges personnalisées.",
"Encadrés d'alerte GFM (Note / Tip / Important / Warning / Caution) en cartes teintées.",
"Raccourcis emoji — :rocket: → 🚀 (~250 couverts).",
"Images SVG rendues nativement. Images à thème respectent clair/sombre. UA navigateur débloque les badges CDN.",
"Blocs de code colorés (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, adapté au thème).",
"Polish Markdown — blockquotes HTML et `` rendus, sub/superscript → unicode, entités HTML décodées.",
"Sections `` dépliables en cartes tap-to-expand. Lignes d'images badge/bouton fluides en ligne.",
"Lien manuel fait confiance à ta version — pas de re-téléchargement pour vérifier.",
"Tri par section — Installées, Avec étoile, Favoris mémorisent chacun leur choix."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Refonte du design — nouvelle typographie Geist, en-tête hero sur Détails, cartes Home redessinées avec glyphes de plateforme, menus style Apple et Bibliothèque rafraîchie avec banner de mises à jour et section 'Prêt à installer'.",
"Disposition deux volets sur tablette — Home, Recherche et Bibliothèque gardent la liste à gauche et ouvrent le repo à droite ; faites glisser le séparateur pour ajuster.",
"Pages internes Détails — À propos et Nouveautés s'ouvrent maintenant comme écrans dédiés avec leur propre retour, et restent dans le volet droit sur tablette.",
"Vraies icônes Apple et Tux pour les indicateurs de plateforme macOS et Linux dans les cartes et listes.",
"Le bureau retient la taille, position et état maximisé de la fenêtre entre les lancements ; les nouvelles fenêtres s'ouvrent centrées au lieu d'en haut à gauche.",
"Lier une app installée recherche désormais aussi dans vos repos favoris — 'Scanner les apps GitHub' propose automatiquement les repos que vous avez mis en favori, vous n'avez donc presque jamais besoin de coller une URL."
]
},
{
"type": "FIXED",
"bullets": [
"Les cartes de découverte affichent maintenant toutes les plateformes avec installateurs, pas seulement celle de l'endpoint.",
"La rangée d'étiquettes Nouveautés ne replie plus les longs tags dans une colonne de date verticale d'un caractère de large.",
"Mismatch de checksum avec un miroir actif — corrigée la race condition entre téléchargements miroir et direct sur le même fichier.",
"La barre de titre Windows 11 correspond maintenant au mode sombre du système au lieu de rester blanche.",
"L'installation silencieuse via root déclenche maintenant correctement la demande de permission Magisk / KernelSU sur Android 14+ au lieu de signaler 'Pas de root' immédiatement ; le chemin root a été réécrit sur libsu.",
"Lier une app installée à un repo GitHub affiche désormais immédiatement 'Mettre à jour vers X' quand la version installée est plus ancienne, au lieu du trompeur 'Installer vX' jusqu'à la prochaine vérification.",
"Le tiroir latéral du bureau affiche maintenant le vrai logo Komi Store au lieu du placeholder 'G'.",
"La largeur de contenu sur bureau (Home, Détails, Auth) se redimensionne maintenant en fraction de la fenêtre — Compact / Large / Extra large s'adaptent à la taille du moniteur au lieu d'être bloqués à des largeurs fixes en pixels.",
"Le bureau Linux ne plante plus au démarrage sur glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — AppImage, deb, rpm et Arch contournent désormais le lanceur empaqueté défectueux et démarrent la JVM directement."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Parcourez les Issues d'un dépôt sans quitter l'app — filtrez les ouvertes ou les fermées, repérez les étiquettes d'un coup d'œil, et ouvrez les fils complets avec commentaires, images et Markdown.",
"Nouvelle page Sécurité par dépôt — les avis de sécurité publiés avec badges de gravité, ainsi que la politique SECURITY.md du projet rendue directement dans l'app.",
"Connectez-vous pour interagir directement — étoilez un dépôt, commentez des issues, ouvrez de nouvelles issues et réagissez avec 👍.",
"Parcourez les pull requests d'un dépôt avec les filtres ouvertes et fermées.",
"Raccourcis sur l'écran d'accueil Android — appuyez longuement sur l'icône de l'app pour aller directement à Rechercher, votre Bibliothèque, vos Favoris ou les Récemment consultés, et faites-en glisser un comme icône autonome.",
"Importez les dépôts étoilés par n'importe quel utilisateur GitHub directement dans vos favoris — sans connexion. Ouvrez Favoris, touchez la nouvelle icône d'ajout de personne, saisissez un nom d'utilisateur et ajoutez les dépôts qui vous intéressent.",
"Vous pouvez désormais sélectionner et copier le nom, la description et les statistiques d'un dépôt sur sa page de détails : appuyez longuement sur le texte pour le copier et le rechercher ailleurs.",
"Windows : une version portable est désormais disponible — décompressez-la et lancez Komi-Store.exe directement, sans installation.",
"Bureau : une barre de menus supérieure plus riche — les nouveaux menus Fichier et Aller permettent d'accéder à l'Accueil, la Recherche, la Bibliothèque, les Favoris ou les Récemment vus, d'ouvrir les paramètres ou de quitter, directement depuis le menu."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 peuvent à nouveau installer le .deb — le paquet n'exige plus les bibliothèques time64 'libasound2t64' / 'libpng16-16t64', qui n'existent que sur Debian 13+, donc un seul .deb s'installe sur toutes les générations de Debian.",
"La connexion sur ordinateur ne reste plus bloquée sur « En attente d'autorisation… » : si le navigateur ne renvoie rien, elle expire désormais pour vous laisser réessayer ou utiliser un code d'appareil ou un jeton.",
"Windows : les liens « Ouvrir dans Komi Store » ouvrent désormais l'application de façon fiable — le gestionnaire githubstore:// est enregistré de manière plus robuste et réenregistré après les mises à jour, si bien que les liens n'échouent plus avec « aucune application associée ».",
"macOS : l'application ne se ferme plus de façon inattendue lorsque vous ouvrez votre profil ou changez de fenêtre."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Fr/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/fr/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Nouvel onglet Explorer — un fil de découverte d'applis installables pour votre plateforme. Il se rafraîchit chaque jour pour qu'il y ait toujours du nouveau et charge plus de contenu au fil du défilement.",
"Nouvel onglet Classements — découvrez les tendances, les nouveautés et les plus populaires, classés sur toute la boutique."
]
},
{
"type": "FIXED",
"bullets": [
"Les téléchargements d'applis choisissent désormais automatiquement la version correspondant au processeur de votre appareil (comme aarch64) au lieu de se rabattre sur un APK universel plus volumineux.",
"Correction de la connexion GitHub sous Windows : l'application de bureau s'ouvre désormais et termine la connexion de manière fiable après l'autorisation dans le navigateur."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Hi/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/hi/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect: इंस्टॉल करने से पहले किसी भी रिलीज़ के अंदर झाँकें।",
"Dhizuku साइलेंट इंस्टॉल — Device Owner के ज़रिए Xiaomi, OPPO, vivo, Huawei डिवाइसों पर OEM इंस्टॉल प्रॉम्प्ट बायपास करें।",
"Obtainium इम्पोर्ट/एक्सपोर्ट — एक टैप से Obtainium से अपनी लाइब्रेरी लाएँ, या जब चाहें Obtainium फ़ॉर्मैट में एक्सपोर्ट करें।",
"Add from starred — अपने GitHub स्टार किए हुए रेपो में से APK वाले को सामने लाएँ।"
]
},
{
"type": "IMPROVED",
"bullets": [
"खुले इश्यू की संख्या और लाइसेंस अब सभी को दिखाई देते हैं, साइन-आउट उपयोगकर्ताओं को भी — बैकएंड से आते हैं, GitHub कोटे पर कोई असर नहीं।",
"बैकग्राउंड अपडेट जाँच को पूरी तरह बंद किया जा सकता है — मैन्युअल जाँच पसंद करते हैं तो बैटरी बचती है।"
]
},
{
"type": "FIXED",
"bullets": [
"लिक्विड ग्लास इफ़ेक्ट हटा दिया गया — डार्क मोड में पारदर्शी पृष्ठभूमि पर आइकन अदृश्य हो सकते थे। हर जगह साफ़, उच्च-कंट्रास्ट UI।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Hi/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/hi/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"ऐप छोड़े बिना किसी रिपॉजिटरी के इश्यूज़ ब्राउज़ करें — खुले या बंद फ़िल्टर करें, एक नज़र में लेबल देखें, और टिप्पणियों, इमेज और Markdown के साथ पूरे इश्यू थ्रेड खोलें।",
"नया प्रति-रिपॉजिटरी सुरक्षा पेज — सेवेरिटी बैज के साथ प्रकाशित सुरक्षा एडवाइज़री, साथ ही प्रोजेक्ट की SECURITY.md नीति इनलाइन रेंडर की गई।",
"सीधे इंटरैक्ट करने के लिए साइन इन करें — किसी रिपो को स्टार करें, इश्यूज़ पर टिप्पणी करें, नए इश्यू खोलें, और 👍 के साथ रिएक्ट करें।",
"किसी रिपॉजिटरी की पुल रिक्वेस्ट को खुले और बंद फ़िल्टर के साथ ब्राउज़ करें।",
"Android होम-स्क्रीन शॉर्टकट — ऐप आइकन को देर तक दबाकर सीधे खोज, अपनी लाइब्रेरी, पसंदीदा या हाल ही में देखा गया पर जाएँ, और किसी को भी अलग लॉन्चर आइकन के रूप में खींचकर रखें।",
"किसी भी GitHub उपयोगकर्ता की स्टार की गई रिपॉजिटरीज़ को सीधे अपने पसंदीदा में आयात करें — साइन इन की ज़रूरत नहीं। पसंदीदा खोलें, नए व्यक्ति-जोड़ें आइकन पर टैप करें, एक यूज़रनेम टाइप करें, और मनचाहे रिपो जोड़ें।",
"अब आप किसी रिपॉज़िटरी के विवरण पृष्ठ पर उसका नाम, विवरण और आँकड़े चुनकर कॉपी कर सकते हैं — टेक्स्ट को देर तक दबाकर कॉपी करें और कहीं और खोजें।",
"Windows: अब एक पोर्टेबल संस्करण उपलब्ध है — अनज़िप करें और सीधे Komi-Store.exe चलाएँ, बिना किसी इंस्टॉलेशन के।",
"डेस्कटॉप: एक समृद्ध शीर्ष मेनू बार — नए फ़ाइल और जाएँ मेनू से सीधे होम, खोज, लाइब्रेरी, पसंदीदा या हाल में देखे गए पर जाएँ, सेटिंग्स खोलें या बाहर निकलें।"
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 अब फिर से .deb इंस्टॉल कर सकते हैं — पैकेज को अब time64 लाइब्रेरीज़ 'libasound2t64' / 'libpng16-16t64' की ज़रूरत नहीं, जो केवल Debian 13+ पर मौजूद हैं, इसलिए एक ही .deb हर Debian संस्करण पर इंस्टॉल हो जाता है।",
"डेस्कटॉप साइन-इन अब “प्राधिकरण की प्रतीक्षा…” पर अटकता नहीं है — अगर ब्राउज़र से वापसी नहीं होती, तो अब यह टाइम-आउट हो जाता है ताकि आप दोबारा कोशिश कर सकें या डिवाइस कोड या टोकन इस्तेमाल कर सकें।",
"Windows: “Open in Komi Store” लिंक अब भरोसे से ऐप खोलते हैं — githubstore:// हैंडलर अधिक मजबूती से पंजीकृत होता है और अपडेट के बाद फिर से पंजीकृत होता है, इसलिए लिंक अब “no application associated” के साथ विफल नहीं होते।",
"macOS: अपनी प्रोफ़ाइल खोलने या विंडो के बीच स्विच करने पर ऐप अब अचानक बंद नहीं होता।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Hi/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/hi/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"नया एक्सप्लोर टैब — आपके प्लैटफ़ॉर्म के लिए इंस्टॉल होने योग्य ऐप्स की खोज फ़ीड। यह हर दिन रिफ़्रेश होता है ताकि हमेशा कुछ नया मिले और स्क्रॉल करते ही और ऐप्स लोड होते हैं।",
"नया टॉप चार्ट टैब — पूरे स्टोर में ट्रेंडिंग, अभी-अभी रिलीज़ हुए और सबसे लोकप्रिय ऐप्स देखें।"
]
},
{
"type": "FIXED",
"bullets": [
"ऐप डाउनलोड अब बड़े यूनिवर्सल APK के बजाय आपके डिवाइस के CPU (जैसे aarch64) से मेल खाने वाला बिल्ड अपने-आप चुनते हैं।",
"Windows पर GitHub साइन-इन ठीक किया गया — ब्राउज़र में अनुमति देने के बाद डेस्कटॉप ऐप अब विश्वसनीय रूप से खुलता है और लॉगिन पूरा करता है।"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/15.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/15.json)
{
"versionCode": 15,
"versionName": "1.8.0",
"releaseDate": "2026-05-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Backend Komi Store: autenticazione, ricerca e scoperta funzionano in Cina.",
"Importazione libreria: rileva in automatico le app GitHub già installate sul dispositivo.",
"Sistema di mirror per il download: gara multi-sorgente con verifica SHA-256.",
"Accesso con Personal Access Token per le reti che bloccano il flusso OAuth nel browser."
]
},
{
"type": "IMPROVED",
"bullets": [
"Invio di feedback dall’app: bug, idee di funzionalità, richieste di modifica.",
"Selettore di canale pre-release e tasto «torna alla versione stabile» nei Dettagli.",
"Pacchetti nativi pkg.tar.zst per Arch Linux, oltre a deb, rpm e AppImage."
]
},
{
"type": "FIXED",
"bullets": [
"Linux Desktop non cancella più in silenzio impostazioni e libreria al riavvio.",
"Scelta della variante rispettata: la variante selezionata si installa senza essere sovrascritta.",
"Risolto il crash di accessibilità su macOS grazie a Compose Multiplatform 1.10.3."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect: esamina il contenuto di una release prima di installarla.",
"Installazione silenziosa con Dhizuku: bypassa i prompt di installazione OEM su Xiaomi, OPPO, vivo e Huawei tramite il proprietario del dispositivo.",
"Import/Export Obtainium: porta la tua libreria da Obtainium con un tocco, o esporta verso il formato Obtainium quando vuoi.",
"Aggiungi dalle stelle: scopri i repo che spediscono APK fra le tue stelle GitHub."
]
},
{
"type": "IMPROVED",
"bullets": [
"Il conteggio delle issue aperte e la licenza ora sono visibili a tutti, anche agli utenti non autenticati — arrivano dal backend, senza costi di quota GitHub.",
"La verifica aggiornamenti in background può essere disattivata del tutto — risparmia batteria se preferisci verificare manualmente."
]
},
{
"type": "FIXED",
"bullets": [
"Effetto vetro liquido rimosso — le icone in modalità scura potevano diventare invisibili su sfondi trasparenti. Interfaccia più pulita e con maggior contrasto ovunque."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Ignora aggiornamenti per app — silenzia la notifica di aggiornamento per le app che non vuoi aggiornare.",
"Salta un aggiornamento specifico — scarta una notifica di aggiornamento se è un falso positivo; verrai avvisato di nuovo quando uscirà una versione più recente.",
"Installazione silenziosa via root — gli utenti di Magisk, KernelSU e APatch possono installare senza Shizuku o Dhizuku."
]
},
{
"type": "FIXED",
"bullets": [
"Le app disinstallate dalle Impostazioni di sistema spariscono ora subito dalla lista delle app tracciate.",
"Riconoscimento versioni più preciso — le release con lo stesso numero ma metadati di build diversi non vengono più erroneamente segnalate come 'già installate'.",
"Aggiornare più app di fila ora funziona in modo affidabile — le installazioni vengono serializzate, così ogni finestra di sistema mostra l'APK giusto. Anche le versioni nella schermata App restano aggiornate dopo ogni installazione.",
"L'aggiornamento automatico sceglie l'APK giusto quando una release include sia la variante normale che quella F-Droid — niente più installazione accidentale di un'app sorella con un ID pacchetto diverso."
]
},
{
"type": "IMPROVED",
"bullets": [
"Aggiornamenti in background più affidabili su Oppo, OnePlus, Realme, Xiaomi, vivo e Honor — le Impostazioni offrono ora una scorciatoia in un tocco per l'esenzione dall'ottimizzazione della batteria, e i job di aggiornamento girano con priorità accelerata.",
"Installazione silenziosa Dhizuku su Android 14+ — l'app riprova automaticamente senza attribuzione dell'installatore quando il sistema richiederebbe una conferma."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Supporto Codeberg + Forgejo + Gitea. Incolla un URL Codeberg / Forgejo o aggiungi il tuo host self-hosted sotto Tweaks → Rete. Dettagli, install, aggiornamenti, ricerca — tutto collegato.",
"Installazione macOS con Homebrew: `brew install --cask github-store`.",
"Accesso GitHub usa il flusso web standard — niente più codice a 8 cifre.",
"Preferenze e credenziali cifrate AES-256-GCM via KSafe (Keystore hardware su Android). Migrazione al primo avvio.",
"Mirror fastly.jsdelivr.net per GitHub limitato.",
"Aderito alla coalizione Keep Android Open — banner lo spiega."
]
},
{
"type": "FIXED",
"bullets": [
"Chip di piattaforma su Dettagli aprono Search filtrato (erano inerti).",
"Pulsante di ricerca della tastiera funziona su Android 12 con IME cinesi.",
"Repo collegato esternamente mostra banner sui Dettagli con un tap per scollegare.",
"Login apre URL del codice precompilato + copia codice facile da incollare.",
"Crash Android 16 / ROM personalizzate su Impostazioni + download — ripiega su archiviazione interna.",
"Rilevamento Magisk / KernelSU / APatch su Android 13+ (sonda mascherata da SELinux).",
"Etichetta variante fissata si aggiorna — niente più numeri beta/rc obsoleti.",
"README / note di rilascio conservano la posizione di scroll oltre le rimozioni dal viewport."
]
},
{
"type": "IMPROVED",
"bullets": [
"Foglio di collegamento manuale ordinato per origine di installazione (F-Droid / Obtainium per primi, aggiornamenti di sistema per ultimi) con chip di origine per app.",
"Smart match suggerisce repo classificati su GitHub + Codeberg + forge personalizzate.",
"Avvisi GFM (Note / Tip / Important / Warning / Caution) come card colorate.",
"Codici emoji — :rocket: → 🚀 (~250 coperti).",
"Immagini SVG renderizzate nativamente. Immagini per tema rispettano chiaro/scuro. UA browser sblocca i badge CDN.",
"Blocchi di codice evidenziati (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, adattato al tema).",
"Rifinitura Markdown — blockquote HTML e `` renderizzano, sub/apice → unicode, entità HTML decodificate.",
"Sezioni `` espandibili come card tap-to-expand. Righe di immagini badge/pulsante scorrono in linea.",
"Collegamento manuale si fida della tua versione — nessun re-download per verificare.",
"Ordinamento per sezione — Installate, Con stella, Preferiti ricordano ognuno la propria scelta."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Restyling del design — nuova tipografia Geist, hero header su Dettagli, card della Home ridisegnate con glifi di piattaforma, menu in stile Apple e Libreria rinnovata con banner aggiornamenti e sezione 'Pronto da installare'.",
"Layout a due pannelli su tablet — Home, Ricerca e Libreria mantengono la lista a sinistra e aprono il repo a destra; trascina il divisore per regolare.",
"Pagine interne Dettagli — Info e Novità si aprono ora come schermate dedicate con il proprio tasto indietro, e restano nel pannello destro su tablet.",
"Icone vere Apple e Tux per gli indicatori di piattaforma macOS e Linux nelle card e liste.",
"Il desktop ricorda dimensione, posizione e stato massimizzato della finestra tra i lanci; le nuove finestre si aprono centrate invece che in alto a sinistra.",
"Collegare un'app installata ora cerca anche tra i tuoi repo con stella — 'Scansiona app GitHub' suggerisce automaticamente i repo che hai contrassegnato con stella, così raramente devi incollare un URL."
]
},
{
"type": "FIXED",
"bullets": [
"Le card di scoperta mostrano ora tutte le piattaforme con installer, non solo quella dell'endpoint.",
"La riga di tag delle Novità non incolonna più i tag lunghi in una colonna data verticale di un carattere.",
"Mismatch di checksum con mirror attivo — corretta la race condition tra download mirror e diretto sullo stesso file.",
"La barra del titolo Windows 11 ora rispetta la modalità scura di sistema invece di restare bianca.",
"L'installazione silenziosa via root attiva correttamente il prompt dei permessi Magisk / KernelSU su Android 14+ invece di riportare subito 'Nessun root'; il percorso root è stato riscritto su libsu.",
"Collegare un'app installata a un repo GitHub mostra subito 'Aggiorna a X' quando la versione installata è più vecchia, invece del fuorviante 'Installa vX' fino al prossimo controllo.",
"Il drawer laterale desktop mostra ora il vero logo di Komi Store invece del placeholder 'G'.",
"La larghezza del contenuto su desktop (Home, Dettagli, Auth) si ridimensiona ora come frazione della finestra — Compatta / Larga / Extra larga si adattano al monitor invece di essere fissate in pixel.",
"Il desktop Linux non va più in crash all'avvio su glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — AppImage, deb, rpm e Arch ora bypassano il launcher impacchettato difettoso e avviano la JVM direttamente."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Sfoglia le Issue di un repository senza uscire dall'app — filtra quelle aperte o chiuse, vedi le etichette a colpo d'occhio e apri i thread completi delle issue con commenti, immagini e Markdown.",
"Nuova pagina Sicurezza per ogni repository — avvisi di sicurezza pubblicati con badge di gravità, più la politica SECURITY.md del progetto visualizzata in linea.",
"Accedi per interagire direttamente — aggiungi una stella a un repo, commenta le issue, apri nuove issue e reagisci con 👍.",
"Sfoglia le Pull request di un repository con i filtri Aperte e Chiuse.",
"Scorciatoie nella schermata Home di Android — tieni premuta l'icona dell'app per andare direttamente a Cerca, Libreria, Preferiti o Visualizzati di recente, e trascinane una come icona autonoma.",
"Importa i repository messi tra le star da qualsiasi utente GitHub direttamente nei tuoi preferiti — senza accesso. Apri Preferiti, tocca la nuova icona aggiungi persona, digita un nome utente e aggiungi i repo che vuoi.",
"Ora puoi selezionare e copiare nome, descrizione e statistiche di un repository nella sua pagina dei dettagli: tieni premuto il testo per copiarlo e cercarlo altrove.",
"Windows: ora è disponibile una versione portatile — estraila ed esegui Komi-Store.exe direttamente, senza installazione.",
"Desktop: una barra dei menu in alto più ricca — i nuovi menu File e Vai ti portano a Home, Ricerca, Libreria, Preferiti o Visti di recente, aprono le impostazioni o chiudono l'app, direttamente dal menu."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 possono di nuovo installare il .deb — il pacchetto non richiede più le librerie time64 'libasound2t64' / 'libpng16-16t64', che esistono solo su Debian 13+, così un unico .deb si installa su tutte le generazioni di Debian.",
"L'accesso da desktop non rimane più bloccato su «In attesa di autorizzazione…»: se il browser non completa l'operazione, ora scade così puoi riprovare o usare un codice dispositivo o un token.",
"Windows: i link «Apri in Komi Store» ora aprono l'app in modo affidabile — il gestore githubstore:// viene registrato in modo più robusto e ri-registrato dopo gli aggiornamenti, così i link non falliscono più con «nessuna applicazione associata».",
"macOS: l'app non si chiude più all'improvviso quando apri il tuo profilo o cambi finestra."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/It/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/it/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Nuova scheda Esplora — un feed di scoperta di app installabili per la tua piattaforma. Si aggiorna ogni giorno così c'è sempre qualcosa di nuovo e carica altri risultati mentre scorri.",
"Nuova scheda Classifiche — scopri cosa è di tendenza, le ultime uscite e le più popolari, in classifica su tutto lo store."
]
},
{
"type": "FIXED",
"bullets": [
"I download delle app ora scelgono automaticamente la versione adatta alla CPU del tuo dispositivo (come aarch64) invece di ripiegare su un APK universale più grande.",
"Risolto l'accesso con GitHub su Windows: l'app desktop ora si apre e completa l'accesso in modo affidabile dopo l'autorizzazione nel browser."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ja/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ja/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"アプリごとに更新を無視 — 更新したくないアプリの更新バッジを非表示にできるようになりました。",
"特定の更新をスキップ — 誤検知の更新通知を1つだけ非表示にできます。新しいバージョンが出れば再び通知されます。",
"Root による静音インストール — Magisk / KernelSU / APatch ユーザーは Shizuku や Dhizuku なしでインストールできるようになりました。"
]
},
{
"type": "FIXED",
"bullets": [
"システム設定からアンインストールしたアプリが、追跡リストからすぐに消えるようになりました。",
"バージョン検出を改善 — 同じバージョン番号でもビルドメタデータが異なるリリースを、誤って『インストール済み』と判定しなくなりました。",
"複数のアプリを連続更新する操作が安定しました — インストールが順番に実行されるため、システムダイアログに前のAPKが表示されることがなくなりました。インストールごとにアプリ画面のバージョンも正しく更新されます。",
"リリースに通常版と F-Droid 版の両方が含まれる場合、自動アップデートが正しい APK を選ぶようになりました — 別のパッケージ ID を持つ姉妹アプリを誤ってインストールしません。"
]
},
{
"type": "IMPROVED",
"bullets": [
"Oppo / OnePlus / Realme / Xiaomi / vivo / Honor でバックグラウンド更新がより確実に — 設定にバッテリー最適化除外へのワンタップショートカットが追加され、更新ワーカーが優先実行されるようになりました。",
"Android 14+ における Dhizuku の静音インストール — システムが確認を求める場合、インストーラ属性なしで自動的に再試行されるようになりました。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ko/15.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ko/15.json)
{
"versionCode": 15,
"versionName": "1.8.0",
"releaseDate": "2026-05-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Komi Store 자체 백엔드 도입. 중국에서도 인증·검색·탐색이 정상 동작합니다.",
"라이브러리 가져오기: 기기에 이미 설치된 GitHub 출처 앱을 자동으로 인식합니다.",
"다운로드 미러 시스템: 다중 소스 경쟁과 SHA-256 무결성 검증을 함께 제공합니다.",
"OAuth 브라우저 로그인이 막힌 환경을 위해 Personal Access Token 로그인을 지원합니다."
]
},
{
"type": "IMPROVED",
"bullets": [
"앱 안에서 피드백 보내기: 버그 신고, 기능 제안, 변경 요청을 바로 보낼 수 있습니다.",
"프리릴리스 채널 칩과 상세 화면의 ‘안정 버전으로 복귀’ 버튼을 추가했습니다.",
"Arch Linux용 pkg.tar.zst 네이티브 패키지를 deb·rpm·AppImage와 함께 제공합니다."
]
},
{
"type": "FIXED",
"bullets": [
"Linux Desktop에서 재시작 시 설정과 라이브러리가 조용히 사라지던 문제를 수정했습니다.",
"선택한 변형(variant)이 덮어쓰기 없이 그대로 설치되도록 수정했습니다.",
"Compose Multiplatform 1.10.3 적용으로 macOS 접근성 크래시를 해결했습니다."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ko/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ko/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Codeberg + Forgejo + Gitea 지원. Codeberg / Forgejo URL을 붙여넣거나 설정 → 네트워크에서 자체 호스트를 추가하세요. 상세, 설치, 업데이트, 검색 — 모두 연결됨.",
"Homebrew로 macOS 설치: `brew install --cask github-store`.",
"GitHub 로그인이 표준 웹 플로우 사용 — 8자리 코드 불필요.",
"환경설정과 자격증명을 KSafe로 AES-256-GCM 암호화 (Android는 하드웨어 Keystore). 첫 실행 시 마이그레이션.",
"GitHub 제한 시 fastly.jsdelivr.net 미러 추가.",
"Keep Android Open 연합 합류 — 배너로 설명."
]
},
{
"type": "FIXED",
"bullets": [
"상세의 플랫폼 칩이 Search를 필터로 엽니다 (이전엔 무반응).",
"Android 12의 키보드 검색 버튼이 중국어 IME에서 작동.",
"외부 연결된 리포는 상세에 한 번 탭으로 해제할 수 있는 배너 표시.",
"로그인이 코드 채워진 URL을 열고 붙여넣기 친화적인 코드를 복사.",
"Android 16 / 커스텀 ROM에서 설정 + 다운로드 크래시 — 내부 저장소로 폴백.",
"Android 13+에서 Magisk / KernelSU / APatch 감지 (SELinux로 가려졌던 검사).",
"고정된 변형 라벨이 새로고침 — 오래된 beta/rc 번호 없음.",
"README / 릴리스 노트가 뷰포트 폐기 사이에서도 스크롤 위치를 유지."
]
},
{
"type": "IMPROVED",
"bullets": [
"수동 연결 시트를 설치 출처별로 정렬(F-Droid / Obtainium 먼저, 시스템 업데이트는 마지막)하고 앱별 출처 칩 표시.",
"Smart match가 GitHub + Codeberg + 사용자 포지의 순위 후보를 제안.",
"GFM 알림(Note / Tip / Important / Warning / Caution)을 색상 카드로 표시.",
"이모지 단축코드 — :rocket: → 🚀 (약 250개 지원).",
"SVG 이미지를 네이티브 렌더링. 테마 이미지는 라이트/다크 따름. 브라우저 UA로 CDN 배지 핫링크 차단 우회.",
"코드 블록에 구문 강조 (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, 테마 대응).",
"Markdown 다듬기 — HTML blockquote와 `` 렌더링, 위/아래첨자 → 유니코드, HTML 엔티티 디코드.",
"`` 접이식 섹션을 탭으로 펼치는 카드로 표시. 배지/버튼 이미지 행이 한 줄에 정렬.",
"수동 매칭은 선택한 버전을 신뢰 — 검증용 재다운로드 불필요.",
"섹션별 정렬 — 설치됨, 별표, 즐겨찾기가 각자의 선택을 기억."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ko/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ko/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"새로운 탐색 탭 — 사용 중인 플랫폼용 설치 가능한 앱을 발견하는 피드입니다. 매일 새로고침되어 늘 새로운 앱이 있고, 스크롤하면 더 불러옵니다.",
"새로운 인기 차트 탭 — 스토어 전체에서 인기 급상승, 방금 출시, 가장 인기 있는 앱을 살펴보세요."
]
},
{
"type": "FIXED",
"bullets": [
"이제 앱 다운로드 시 더 큰 범용 APK 대신 기기의 CPU(예: aarch64)에 맞는 빌드를 자동으로 선택합니다.",
"Windows에서 GitHub 로그인 문제를 수정했습니다 — 브라우저에서 인증한 후 데스크톱 앱이 안정적으로 열리고 로그인을 완료합니다."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect — zajrzyj do środka dowolnego wydania przed instalacją.",
"Cicha instalacja przez Dhizuku — pomijaj okna instalacji OEM na urządzeniach Xiaomi, OPPO, vivo i Huawei dzięki uprawnieniom właściciela urządzenia.",
"Import/Eksport Obtainium — przenieś bibliotekę z Obtainium jednym dotknięciem albo wyeksportuj do formatu Obtainium kiedy chcesz.",
"Dodaj z oznaczonych gwiazdką — zobacz, które z twoich oznaczonych repo GitHub publikują APK."
]
},
{
"type": "IMPROVED",
"bullets": [
"Liczba otwartych zgłoszeń i licencja są teraz pokazywane wszystkim, także użytkownikom niezalogowanym — pochodzą z backendu, bez kosztów limitu GitHuba.",
"Sprawdzanie aktualizacji w tle można całkowicie wyłączyć — oszczędza baterię, jeśli wolisz sprawdzać ręcznie."
]
},
{
"type": "FIXED",
"bullets": [
"Efekt płynnego szkła usunięty — w trybie ciemnym ikony na przezroczystym tle mogły stawać się niewidoczne. Wszędzie czystszy, bardziej kontrastowy interfejs."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Ignorowanie aktualizacji dla każdej aplikacji — wycisz powiadomienie o aktualizacji dla dowolnej aplikacji, której nie chcesz aktualizować.",
"Pomiń konkretną aktualizację — odrzuć fałszywy alarm aktualizacji; gdy pojawi się nowsza wersja, zostaniesz powiadomiony ponownie.",
"Cicha instalacja przez root — użytkownicy Magisk, KernelSU i APatch mogą instalować bez Shizuku lub Dhizuku."
]
},
{
"type": "FIXED",
"bullets": [
"Aplikacje odinstalowane przez ustawienia systemu znikają teraz natychmiast z listy śledzonych.",
"Lepsze wykrywanie wersji — wydania o tym samym numerze, ale z różnymi metadanymi build, nie są już błędnie oznaczane jako 'już zainstalowane'.",
"Aktualizowanie wielu aplikacji po kolei działa teraz niezawodnie — instalacje są szeregowane, więc okno dialogowe systemu nie pokazuje już poprzedniego APK. Wersje na ekranie aplikacji również są aktualizowane po każdej instalacji.",
"Automatyczna aktualizacja wybiera właściwy APK, gdy wydanie zawiera zarówno wariant zwykły, jak i F-Droid — koniec z przypadkowym instalowaniem siostrzanej aplikacji z innym ID pakietu."
]
},
{
"type": "IMPROVED",
"bullets": [
"Bardziej niezawodne aktualizacje w tle na Oppo, OnePlus, Realme, Xiaomi, vivo i Honor — Ustawienia oferują teraz skrót do wyłączenia optymalizacji baterii w jednym kliknięciu, a zadania aktualizacji działają z przyspieszonym priorytetem.",
"Cicha instalacja Dhizuku na Androidzie 14+ — aplikacja automatycznie ponawia bez atrybucji instalatora, gdy system wymagałby potwierdzenia."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Wsparcie Codeberg + Forgejo + Gitea. Wklej URL Codeberg / Forgejo lub dodaj własny host pod Tweaks → Sieć. Szczegóły, install, aktualizacje, wyszukiwanie — wszystko podłączone.",
"Instalacja na macOS przez Homebrew: `brew install --cask github-store`.",
"Logowanie GitHub używa standardowego przepływu webowego — bez 8-cyfrowego kodu.",
"Preferencje i dane uwierzytelniające szyfrowane AES-256-GCM przez KSafe (sprzętowy Keystore na Androidzie). Migracja przy pierwszym uruchomieniu.",
"Mirror fastly.jsdelivr.net dla ograniczonego GitHub.",
"Dołączyliśmy do koalicji Keep Android Open — baner wyjaśnia."
]
},
{
"type": "FIXED",
"bullets": [
"Kafelki platformy w Szczegółach otwierają Search z filtrem (były nieaktywne).",
"Przycisk wyszukiwania klawiatury działa na Android 12 z chińskimi IME.",
"Zewnętrznie powiązane repo pokazuje baner w Szczegółach z jednym kliknięciem rozłączenia.",
"Logowanie otwiera URL kodu wstępnie wypełniony + kopiuje wersję przyjazną do wklejania.",
"Crash na Android 16 / niestandardowych ROM w Ustawieniach + pobieraniu — przełącza na pamięć wewnętrzną.",
"Wykrywanie Magisk / KernelSU / APatch na Android 13+ (sonda maskowana przez SELinux).",
"Etykieta przypiętego wariantu odświeża się — bez przestarzałych numerów beta/rc.",
"README / notatki wydania zachowują pozycję przewijania po usunięciu z viewportu."
]
},
{
"type": "IMPROVED",
"bullets": [
"Arkusz ręcznego powiązania sortuje wg źródła instalatora (F-Droid / Obtainium na początku, aktualizacje systemu na końcu) z chipem źródła dla aplikacji.",
"Smart match proponuje uszeregowane repo z GitHub + Codeberg + niestandardowe forge.",
"Wyróżnienia GFM (Note / Tip / Important / Warning / Caution) jako kolorowe karty.",
"Skróty emoji — :rocket: → 🚀 (~250 pokrytych).",
"Obrazy SVG renderują natywnie. Obrazy tematyczne respektują jasny/ciemny. UA przeglądarki odblokuje badge'e CDN.",
"Bloki kodu z podświetlaniem składni (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, dopasowane do motywu).",
"Szlif Markdown — blockquote HTML i `` renderują, indeksy → unicode, encje HTML zdekodowane.",
"Rozwijane sekcje `` jako karty tap-to-expand. Wiersze obrazów odznak/przycisków płyną w linii.",
"Ręczne powiązanie ufa twojej wersji — bez ponownego pobierania do weryfikacji.",
"Sortowanie zależne od sekcji — Zainstalowane, Z gwiazdką, Ulubione pamiętają swój wybór."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Przebudowa designu — nowa typografia Geist, hero header na Szczegółach, przeprojektowane karty Home z glifami platform, menu w stylu Apple i odświeżona Biblioteka z bannerem aktualizacji i sekcją 'Gotowe do instalacji'.",
"Układ dwupanelowy na tablecie — Home, Wyszukiwanie i Biblioteka trzymają listę po lewej i otwierają repo po prawej; przeciągnij separator, by zmienić rozmiar.",
"Wewnętrzne strony Szczegółów — Informacje i Co nowego otwierają się teraz jako dedykowane ekrany z własną akcją cofania i pozostają w prawym panelu na tablecie.",
"Prawdziwe ikony Apple i Tux dla wskaźników platform macOS i Linux w kartach i listach.",
"Desktop pamięta rozmiar, pozycję i stan zmaksymalizowany okna między uruchomieniami; nowe okna otwierają się wyśrodkowane zamiast w lewym górnym rogu.",
"Powiązanie zainstalowanej aplikacji dopasowuje teraz także twoje repozytoria z gwiazdką — 'Skanuj aplikacje GitHub' automatycznie podpowiada repozytoria oznaczone gwiazdką, więc rzadko musisz wklejać URL."
]
},
{
"type": "FIXED",
"bullets": [
"Karty odkrywania pokazują teraz wszystkie platformy z instalatorami, nie tylko tę z endpointu.",
"Wiersz tagów Co nowego nie zawija już długich tagów w pionową kolumnę daty o szerokości jednego znaku.",
"Niezgodność sumy kontrolnej przy aktywnym mirrorze — naprawiono race condition między pobraniami z mirrora i bezpośrednim do tego samego pliku.",
"Pasek tytułu Windows 11 dopasowuje się teraz do trybu ciemnego systemu zamiast pozostawać biały.",
"Cicha instalacja przez root prawidłowo wyzwala teraz prompt uprawnień Magisk / KernelSU na Androidzie 14+ zamiast natychmiast zgłaszać 'Brak roota'; ścieżka roota została przepisana na libsu.",
"Powiązanie zainstalowanej aplikacji z repo GitHub pokazuje teraz od razu 'Aktualizuj do X', gdy zainstalowana wersja jest starsza, zamiast mylącego 'Instaluj vX' do następnego sprawdzenia aktualizacji.",
"Boczna szuflada desktop pokazuje teraz prawdziwe logo Komi Store zamiast placeholdera 'G'.",
"Szerokość zawartości na desktopie (Home, Szczegóły, Auth) skaluje się teraz jako ułamek okna — Kompaktowa / Szeroka / Bardzo szeroka dostosowują się do monitora zamiast być ograniczone do stałych szerokości w pikselach.",
"Desktop Linux nie ulega już awarii przy uruchamianiu na glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — AppImage, deb, rpm i Arch omijają teraz wadliwy dołączony launcher i uruchamiają JVM bezpośrednio."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Przeglądaj zgłoszenia repozytorium bez wychodzenia z aplikacji — filtruj otwarte lub zamknięte, zobacz etykiety na pierwszy rzut oka i otwieraj pełne wątki zgłoszeń z komentarzami, obrazami i Markdown.",
"Nowa strona Bezpieczeństwo dla każdego repozytorium — opublikowane zalecenia bezpieczeństwa z oznaczeniami ważności oraz polityka SECURITY.md projektu renderowana bezpośrednio na stronie.",
"Zaloguj się, aby działać bezpośrednio — oznacz repozytorium gwiazdką, komentuj zgłoszenia, otwieraj nowe zgłoszenia i reaguj za pomocą 👍.",
"Przeglądaj pull requesty repozytorium z filtrami otwartych i zamkniętych.",
"Skróty na ekranie głównym Androida — przytrzymaj ikonę aplikacji, aby przejść od razu do Szukaj, Biblioteki, Ulubionych lub Ostatnio oglądanych, i przeciągnij dowolny jako osobną ikonę.",
"Importuj oznaczone gwiazdką repozytoria dowolnego użytkownika GitHuba prosto do swoich ulubionych — bez logowania. Otwórz Ulubione, dotknij nowej ikony dodawania osoby, wpisz nazwę użytkownika i dodaj wybrane repozytoria.",
"Możesz teraz zaznaczyć i skopiować nazwę, opis oraz statystyki repozytorium na jego stronie szczegółów — przytrzymaj tekst, aby go skopiować i wyszukać gdzie indziej.",
"Windows: dostępna jest teraz wersja przenośna — rozpakuj i uruchom Komi-Store.exe bezpośrednio, bez instalacji.",
"Pulpit: bogatszy górny pasek menu — nowe menu Plik i Idź pozwalają przejść do ekranu głównego, wyszukiwania, biblioteki, ulubionych lub ostatnio oglądanych, otworzyć ustawienia albo zamknąć aplikację, bezpośrednio z menu."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 znów mogą zainstalować pakiet .deb — nie wymaga już bibliotek time64 'libasound2t64' / 'libpng16-16t64', które istnieją tylko w Debianie 13+, więc jeden .deb instaluje się na wszystkich generacjach Debiana.",
"Logowanie na komputerze nie zacina się już na „Oczekiwanie na autoryzację…” — jeśli przeglądarka nie odeśle odpowiedzi, następuje teraz przekroczenie limitu czasu, więc możesz spróbować ponownie lub użyć kodu urządzenia albo tokena.",
"Windows: linki „Otwórz w Komi Store” niezawodnie otwierają aplikację — obsługa githubstore:// jest rejestrowana solidniej i ponownie po aktualizacjach, więc linki nie kończą się już błędem „brak skojarzonej aplikacji”.",
"macOS: aplikacja nie zamyka się już nieoczekiwanie po otwarciu profilu lub przełączaniu okien."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Pl/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/pl/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Nowa karta Odkrywaj — strumień odkryć instalowalnych aplikacji dla Twojej platformy. Odświeża się codziennie, więc zawsze jest coś nowego i dogrywa kolejne aplikacje podczas przewijania.",
"Nowa karta Rankingi — przeglądaj to, co na czasie, dopiero wydane i najpopularniejsze w całym sklepie."
]
},
{
"type": "FIXED",
"bullets": [
"Pobierane aplikacje automatycznie wybierają wersję pasującą do procesora Twojego urządzenia (np. aarch64) zamiast większego, uniwersalnego pliku APK.",
"Naprawiono logowanie przez GitHub w systemie Windows — aplikacja desktopowa teraz niezawodnie otwiera się i kończy logowanie po autoryzacji w przeglądarce."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ru/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ru/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Поддержка Codeberg + Forgejo + Gitea. Вставьте URL Codeberg / Forgejo или добавьте свой self-hosted хост в Tweaks → Сеть. Детали, установка, обновления, поиск — всё подключено.",
"Установка на macOS через Homebrew: `brew install --cask github-store`.",
"Вход через GitHub использует стандартный веб-поток — без 8-значного кода.",
"Настройки и учётные данные шифруются AES-256-GCM через KSafe (аппаратный Keystore на Android). Миграция при первом запуске.",
"Зеркало fastly.jsdelivr.net для ограниченного GitHub.",
"Присоединились к коалиции Keep Android Open — баннер объясняет."
]
},
{
"type": "FIXED",
"bullets": [
"Чипы платформ в Деталях открывают Search с фильтром (раньше не работали).",
"Кнопка поиска клавиатуры работает на Android 12 с китайскими IME.",
"Внешне связанный репозиторий показывает баннер в Деталях с одной кнопкой отвязки.",
"Вход открывает URL кода с заполненным кодом + копирует версию для вставки.",
"Сбой Android 16 / кастомных ROM в Настройках + загрузках — переключается на внутреннее хранилище.",
"Обнаружение Magisk / KernelSU / APatch на Android 13+ (проверка скрывалась SELinux).",
"Шильдик закреплённого варианта обновляется — без устаревших beta/rc номеров.",
"README / заметки релиза сохраняют позицию прокрутки при пересоздании элементов viewport."
]
},
{
"type": "IMPROVED",
"bullets": [
"Лист ручной привязки сортирован по источнику установки (F-Droid / Obtainium первыми, системные обновления — последними), с чипом источника для приложения.",
"Smart match предлагает ранжированные репозитории из GitHub + Codeberg + свои форджи.",
"Выделения GFM (Note / Tip / Important / Warning / Caution) как цветные карточки.",
"Эмодзи-коды — :rocket: → 🚀 (~250 покрыто).",
"SVG-изображения рендерятся нативно. Тематические изображения учитывают светлую/тёмную тему. UA браузера обходит блокировку CDN-бейджей.",
"Блоки кода с подсветкой синтаксиса (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, адаптировано к теме).",
"Полировка Markdown — HTML-цитаты и `` рендерятся, индексы → unicode, HTML-сущности декодируются.",
"Сворачиваемые секции `` как карточки tap-to-expand. Строки бейджей/кнопок плывут в одной линии.",
"Ручная привязка доверяет вашей версии — без повторной загрузки для проверки.",
"Посекционная сортировка — Установленные, Помеченные, Избранные помнят свой выбор."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ru/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ru/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Переработка дизайна — новая типографика Geist, hero-заголовок в Деталях, переработанные карточки Home с глифами платформ, меню в стиле Apple и обновлённая Библиотека с баннером обновлений и секцией 'Готово к установке'.",
"Двухпанельный режим на планшете — Home, Поиск и Библиотека держат список слева и открывают репозиторий справа; перетащите разделитель для изменения размера.",
"Внутренние страницы Деталей — О приложении и Что нового теперь открываются как отдельные экраны со своей кнопкой назад и остаются в правой панели на планшете.",
"Настоящие иконки Apple и Tux для индикаторов платформ macOS и Linux в карточках и списках.",
"Десктоп запоминает размер, позицию и развёрнутое состояние окна между запусками; новые окна открываются по центру, а не в левом верхнем углу.",
"Привязка установленного приложения теперь также ищет среди ваших репозиториев со звездой — 'Сканировать приложения GitHub' автоматически предлагает отмеченные звездой репозитории, так что URL вставлять почти не нужно."
]
},
{
"type": "FIXED",
"bullets": [
"Карточки открытия теперь показывают все платформы с установщиками, а не только ту, что была в endpoint'е.",
"Строка тегов Что нового больше не сворачивает длинные теги релизов в вертикальную колонку даты шириной в один символ.",
"Несовпадение контрольной суммы при активном зеркале — исправлен race condition между загрузками с зеркала и прямой на один и тот же файл.",
"Заголовок окна Windows 11 теперь соответствует тёмной теме системы, а не остаётся белым.",
"Тихая установка через root теперь правильно вызывает запрос прав Magisk / KernelSU на Android 14+, а не сразу сообщает 'Нет root'; путь root был переписан на libsu.",
"Привязка установленного приложения к GitHub-репозиторию теперь сразу показывает 'Обновить до X', когда установленная версия старее, вместо вводящего в заблуждение 'Установить vX' до следующей проверки обновлений.",
"Боковая панель десктопа теперь показывает настоящий логотип Komi Store вместо заглушки 'G'.",
"Ширина контента на десктопе (Home, Детали, Auth) теперь масштабируется как доля окна — Компактная / Широкая / Очень широкая адаптируются к размеру монитора вместо фиксированной ширины в пикселях.",
"Десктоп Linux больше не падает при запуске на glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) — сборки AppImage, deb, rpm и Arch теперь обходят сломанный встроенный лаунчер и запускают JVM напрямую."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ru/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ru/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Просматривай Issues репозитория, не покидая приложение — фильтруй открытые или закрытые, смотри метки с первого взгляда и открывай полные треды issue с комментариями, изображениями и Markdown.",
"Новая страница «Безопасность» для каждого репозитория — опубликованные уведомления о безопасности с бейджами серьёзности, а также политика SECURITY.md проекта, отрисованная прямо здесь.",
"Войди, чтобы взаимодействовать напрямую — отмечай репозиторий звездой, комментируй issue, создавай новые issue и реагируй с 👍.",
"Просматривай pull request'ы репозитория с фильтрами открытых и закрытых.",
"Ярлыки на главном экране Android — зажми значок приложения, чтобы сразу перейти к Поиску, своей Библиотеке, Избранному или Недавно просмотренным, и вынеси любой из них как отдельный значок.",
"Импортируй репозитории, отмеченные звездой любым пользователем GitHub, прямо в избранное — без входа в аккаунт. Открой Избранное, нажми новую иконку добавления человека, введи имя пользователя и добавь нужные репозитории.",
"Теперь можно выделить и скопировать название, описание и статистику репозитория на странице сведений — нажмите и удерживайте текст, чтобы скопировать его и найти в другом месте.",
"Windows: теперь доступна портативная версия — распакуйте и запустите Komi-Store.exe напрямую, без установки.",
"Рабочий стол: более насыщенная верхняя строка меню — новые меню «Файл» и «Переход» позволяют перейти на главную, к поиску, библиотеке, избранному или недавно просмотренным, открыть настройки или выйти прямо из меню."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 снова могут установить .deb — пакет больше не требует библиотеки time64 'libasound2t64' / 'libpng16-16t64', которые есть только в Debian 13+, поэтому один .deb устанавливается на всех поколениях Debian.",
"Вход на компьютере больше не зависает на «Ожидание авторизации…» — если браузер не возвращает ответ, теперь срабатывает тайм-аут, и вы можете повторить попытку или использовать код устройства либо токен.",
"Windows: ссылки «Открыть в Komi Store» теперь надёжно открывают приложение — обработчик githubstore:// регистрируется более надёжно и повторно после обновлений, поэтому ссылки больше не завершаются ошибкой «нет связанного приложения».",
"macOS: приложение больше не закрывается неожиданно при открытии профиля или переключении между окнами."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Ru/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/ru/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Новая вкладка «Обзор» — лента подборки устанавливаемых приложений для вашей платформы. Она обновляется каждый день, поэтому всегда есть что-то новое и подгружает приложения по мере прокрутки.",
"Новая вкладка «Топ-чарты» — смотрите, что в тренде, что только вышло и что популярнее всего, по всему магазину."
]
},
{
"type": "FIXED",
"bullets": [
"Загрузка приложений теперь автоматически выбирает сборку под процессор вашего устройства (например, aarch64), а не более крупный универсальный APK.",
"Исправлен вход через GitHub в Windows — десктоп-приложение теперь надёжно открывается и завершает вход после авторизации в браузере."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/15.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/15.json)
{
"versionCode": 15,
"versionName": "1.8.0",
"releaseDate": "2026-05-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Komi Store kendi arka ucu: kimlik doğrulama, arama ve keşfetme Çin’de de çalışıyor.",
"Kütüphane içe aktarma: cihazda zaten kurulu olan GitHub uygulamalarını otomatik tanır.",
"İndirme ayna sistemi: çoklu kaynak yarışı ve SHA-256 doğrulaması.",
"OAuth tarayıcı akışını engelleyen ağlar için Personal Access Token ile giriş."
]
},
{
"type": "IMPROVED",
"bullets": [
"Uygulama içinden geri bildirim: hata raporları, özellik fikirleri, değişiklik istekleri.",
"Detaylar ekranında ön sürüm kanal seçici ve “kararlıya geri dön” düğmesi.",
"Arch Linux için yerel pkg.tar.zst paketleri; deb, rpm ve AppImage’in yanı sıra."
]
},
{
"type": "FIXED",
"bullets": [
"Linux Desktop yeniden başlatmada artık ayarları ve kütüphaneyi sessizce silmiyor.",
"Seçilen varyant artık üzerine yazılmadan, olduğu gibi yükleniyor.",
"Compose Multiplatform 1.10.3 güncellemesiyle macOS erişilebilirlik çökmesi giderildi."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect: kurmadan önce herhangi bir sürümün içine göz at.",
"Dhizuku ile sessiz kurulum — Xiaomi, OPPO, vivo, Huawei cihazlarında OEM kurulum istemlerini Cihaz Sahibi yetkisiyle atlayın.",
"Obtainium içe/dışa aktarma — Obtainium kütüphanenizi tek dokunuşla getirin ya da istediğiniz zaman Obtainium biçiminde dışa aktarın.",
"Yıldızlananlardan ekle — GitHub'da yıldızladıklarınız arasından APK gönderenleri görün."
]
},
{
"type": "IMPROVED",
"bullets": [
"Açık konu sayısı ve lisans artık oturum açmamış kullanıcılar dahil herkese gösteriliyor — backend'den geliyor, GitHub kotası harcamıyor.",
"Arka plan güncelleme kontrolü tamamen kapatılabiliyor — manuel kontrolü tercih ediyorsanız pil tasarrufu sağlar."
]
},
{
"type": "FIXED",
"bullets": [
"Sıvı cam efekti kaldırıldı — koyu modda ikonlar şeffaf arka planlarda görünmez olabiliyordu. Her yerde daha temiz, daha kontrastlı bir arayüz."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Uygulama bazında güncelleme yok say — güncellemek istemediğin uygulamaların güncelleme rozetini sustur.",
"Belirli bir güncellemeyi atla — yanlış bir güncelleme uyarısını yok sayabilirsin; daha yeni bir sürüm geldiğinde tekrar bildirim alırsın.",
"Root ile sessiz yükleme — Magisk, KernelSU ve APatch kullanıcıları artık Shizuku veya Dhizuku olmadan yükleyebilir."
]
},
{
"type": "FIXED",
"bullets": [
"Sistem ayarlarından kaldırılan uygulamalar artık izlenen listeden anında siliniyor.",
"Daha iyi sürüm algılama — aynı numarayı paylaşan ancak farklı build meta verisi taşıyan sürümler artık yanlışlıkla 'zaten yüklü' olarak işaretlenmiyor.",
"Birkaç uygulamayı arka arkaya güncellemek artık güvenilir — yüklemeler sıralı çalıştığı için sistem diyaloğu önceki APK'yi göstermiyor. Her yüklemenin ardından Uygulamalar ekranındaki sürümler de doğru biçimde güncelleniyor.",
"Bir sürüm hem standart hem F-Droid varyantı içerdiğinde otomatik güncelleme doğru APK'yi seçer — farklı paket kimliğine sahip kardeş bir uygulamayı yanlışlıkla yüklemek artık yok."
]
},
{
"type": "IMPROVED",
"bullets": [
"Oppo, OnePlus, Realme, Xiaomi, vivo ve Honor'da arka plan güncellemeleri daha güvenilir — Ayarlar artık pil optimizasyonundan tek dokunuşla muafiyet kısayolu sunuyor ve güncelleme görevleri öncelikli (expedited) çalışıyor.",
"Android 14+ üzerinde Dhizuku sessiz yüklemesi — sistem onay isteyeceği durumlarda uygulama otomatik olarak yükleyici atfı olmadan yeniden dener."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/18.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/18.json)
{
"versionCode": 18,
"versionName": "1.8.3",
"releaseDate": "2026-05-14",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Codeberg + Forgejo + Gitea desteği. Codeberg / Forgejo URL'sini yapıştır veya Ayarlar → Ağ altında kendi host'unu ekle. Detaylar, kurulum, güncellemeler, arama — tümü bağlı.",
"Homebrew ile macOS kurulumu: `brew install --cask github-store`.",
"GitHub girişi standart web akışını kullanır — 8 haneli kod yok.",
"Tercihler ve kimlik bilgileri KSafe ile AES-256-GCM şifreli (Android'de donanım Keystore). İlk açılışta taşıma.",
"Kısıtlı GitHub için fastly.jsdelivr.net mirror eklendi.",
"Keep Android Open koalisyonuna katıldık — banner açıklıyor."
]
},
{
"type": "FIXED",
"bullets": [
"Detaylar'daki platform çipleri filtrelenmiş Search açıyor (önceden tepkisizdi).",
"Klavye arama düğmesi Android 12'de Çince IME'lerle çalışıyor.",
"Harici bağlanmış depo Detaylar'da tek dokunuşla bağlantı kaldırma banner'ı gösteriyor.",
"Oturum açma önceden doldurulmuş kod URL'sini açıyor + yapıştırmaya uygun kodu kopyalıyor.",
"Android 16 / özel ROM'larda Ayarlar + indirme çökmesi — dahili depolamaya geçer.",
"Android 13+ üzerinde Magisk / KernelSU / APatch algılama (SELinux ile maskelenmiş sonda).",
"Sabitlenmiş varyant etiketi yenileniyor — eski beta/rc numaraları yok.",
"README / sürüm notları viewport temizlikleri arası kaydırma konumunu koruyor."
]
},
{
"type": "IMPROVED",
"bullets": [
"Manuel bağlama sayfası yükleyici kaynağına göre sıralı (önce F-Droid / Obtainium, en sonda sistem güncellemeleri), uygulama başına kaynak çipi.",
"Smart match GitHub + Codeberg + özel forge'lardan sıralı depo öneriyor.",
"GFM uyarıları (Note / Tip / Important / Warning / Caution) renkli kartlar olarak.",
"Emoji kısayolları — :rocket: → 🚀 (~250 kapsanır).",
"SVG görselleri doğrudan render. Temaya özel görseller açık/koyu'ya saygı duyar. Tarayıcı UA CDN rozet engelini aşar.",
"Kod bloklarında sözdizimi vurgulama (Kotlin / Java / Python / JS/TS / Rust / Swift / C# / Ruby / Shell, temaya uyumlu).",
"Markdown rötuşu — HTML blockquote'ları ve `` render, alt/üst → unicode, HTML varlıkları çözülür.",
"Daraltılabilir `` bölümleri dokunmayla açılan kartlar. Rozet/buton görsel satırları tek satırda akar.",
"Manuel eşleme seçtiğin sürüme güvenir — doğrulama için yeniden indirme yok.",
"Bölüme özel sıralama — Yüklü, Yıldızlı, Favoriler kendi tercihini hatırlar."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/19.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/19.json)
{
"versionCode": 19,
"versionName": "1.9.0",
"releaseDate": "2026-05-23",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Tasarım yenilemesi — yeni Geist tipografisi, Detaylar'da hero başlık, platform glifli yeniden tasarlanmış Home kartları, Apple tarzı menüler ve güncelleme banner'ı ile 'Yüklenmeye hazır' bölümlü yenilenmiş Kitaplık.",
"Tablette iki panel düzeni — Home, Arama ve Kitaplık listeyi solda tutar ve repo'yu sağda açar; ayırıcıyı sürükleyerek boyutlandır.",
"İç Detay sayfaları — Hakkında ve Yenilikler artık kendi geri eylemleriyle özel ekranlar olarak açılır ve tablette sağ panelde kalır.",
"macOS ve Linux platform göstergeleri için kartlarda ve listelerde gerçek Apple ve Tux ikonları.",
"Masaüstü, son pencere boyutu, konumu ve büyütülmüş durumu lansmanlar arasında hatırlar; yeni pencereler sol üst köşe yerine ortalanmış açılır.",
"Yüklü bir uygulamayı bağlamak artık yıldızladığınız repo'larla da eşleşiyor — 'GitHub uygulamalarını tara' yıldızladığınız repo'ları otomatik önerir, böylece nadiren URL yapıştırmanız gerekir."
]
},
{
"type": "FIXED",
"bullets": [
"Keşif kartları artık endpoint'in listelediği değil, repo'nun installer gönderdiği her platformu gösterir.",
"Yenilikler etiket satırı artık uzun release etiketlerini bir karakter genişliğindeki dikey tarih sütununa sarmıyor.",
"Mirror aktifken checksum uyuşmazlığı — aynı hedef dosyaya yazan mirror ve doğrudan indirmeler arasındaki race condition düzeltildi.",
"Windows 11 başlık çubuğu artık göz alıcı beyaz kalmak yerine sistem koyu modunu yansıtıyor.",
"Root ile sessiz yükleme artık 'Root yok' hatasını anında bildirmek yerine Android 14+ üzerinde Magisk / KernelSU izin istemini düzgün tetikliyor; root yolu libsu üzerine yeniden yazıldı.",
"Yüklü bir uygulamayı GitHub repo'suna bağlamak, yüklü sürüm daha eskiyse artık yanıltıcı 'Yükle vX' yerine hemen 'X sürümüne güncelle' gösterir.",
"Masaüstü yan çekmecesi artık 'G' placeholder'ı yerine gerçek Komi Store logosunu gösteriyor.",
"Masaüstü içerik genişliği (Home, Detaylar, Auth) artık pencerenin kesri olarak ölçekleniyor — Kompakt / Geniş / Çok geniş, sabit piksel genişliklerinde sınırlı kalmak yerine monitör boyutuna uyum sağlıyor.",
"Linux masaüstü artık glibc 2.42+ (Fedora 43, Ubuntu 26.04, Debian 13, Bazzite) üzerinde başlatılırken çökmüyor — AppImage, deb, rpm ve Arch yapıları artık bozuk paketlenmiş başlatıcıyı atlayıp JVM'yi doğrudan başlatıyor."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/20.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/20.json)
{
"versionCode": 20,
"versionName": "1.9.1",
"releaseDate": "2026-06-01",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Bir reponun Issue'larına uygulamadan ayrılmadan göz atın — açık veya kapalı olanları filtreleyin, etiketleri bir bakışta görün ve yorumlar, görseller ve Markdown içeren issue başlıklarını tam olarak açın.",
"Her repoya özel yeni Güvenlik sayfası — önem rozetli yayımlanmış güvenlik danışma bültenleri ve projenin SECURITY.md politikası satır içinde işlenmiş olarak.",
"Doğrudan etkileşim için giriş yapın — bir repoyu yıldızlayın, sorunlara yorum yapın, yeni issue'lar açın ve 👍 ile tepki verin.",
"Bir deponun Pull request'lerine açık ve kapalı filtreleriyle göz atın.",
"Android ana ekran kısayolları — uygulama simgesine uzun basarak doğrudan Ara, Kütüphane, Favoriler veya Son görüntülenenlere geç ve herhangi birini bağımsız bir simge olarak sürükle.",
"Herhangi bir GitHub kullanıcısının yıldızladığı depoları doğrudan favorilerinize aktarın — giriş yapmaya gerek yok. Favoriler'i açın, yeni kişi-ekle simgesine dokunun, bir kullanıcı adı yazın ve istediğiniz depoları ekleyin.",
"Artık bir deponun ayrıntı sayfasında adını, açıklamasını ve istatistiklerini seçip kopyalayabilirsiniz — metni uzun basılı tutarak kopyalayın ve başka bir yerde aratın.",
"Windows: artık taşınabilir bir sürüm mevcut — arşivden çıkarıp Komi-Store.exe'yi doğrudan çalıştırın, kuruluma gerek yok.",
"Masaüstü: daha zengin bir üst menü çubuğu — yeni Dosya ve Git menüleriyle doğrudan menüden Ana Sayfa, Arama, Kütüphane, Favoriler veya Son Görüntülenenler'e gidin, ayarları açın ya da çıkın."
]
},
{
"type": "FIXED",
"bullets": [
"Debian 12 / Ubuntu 22.04 artık .deb paketini yeniden kurabiliyor — paket, yalnızca Debian 13+ üzerinde bulunan time64 'libasound2t64' / 'libpng16-16t64' kitaplıklarını artık istemiyor, böylece tek bir .deb tüm Debian sürümlerine kuruluyor.",
"Masaüstünde oturum açma artık «Yetkilendirme bekleniyor…» ekranında takılıp kalmıyor — tarayıcıdan yanıt gelmezse artık zaman aşımına uğruyor; böylece yeniden deneyebilir ya da cihaz kodu veya belirteç kullanabilirsiniz.",
"Windows: «Komi Store'da Aç» bağlantıları artık uygulamayı güvenilir şekilde açıyor — githubstore:// işleyicisi daha sağlam biçimde ve güncellemelerden sonra yeniden kaydediliyor, böylece bağlantılar artık «ilişkili uygulama yok» hatasıyla başarısız olmuyor.",
"macOS: profilinizi açtığınızda veya pencereler arasında geçiş yaptığınızda uygulama artık beklenmedik şekilde kapanmıyor."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Tr/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/tr/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"Yeni Keşfet sekmesi — platformun için yüklenebilir uygulamaların keşif akışı. Her gün yenilenir, böylece her zaman yeni bir şeyler olur ve kaydırdıkça daha fazlasını yükler.",
"Yeni En Popüler sekmesi — mağazanın tamamında öne çıkanları, yeni çıkanları ve en popülerleri gör."
]
},
{
"type": "FIXED",
"bullets": [
"Uygulama indirmeleri artık daha büyük evrensel APK yerine cihazınızın işlemcisine (örneğin aarch64) uygun sürümü otomatik olarak seçiyor.",
"Windows'ta GitHub ile oturum açma sorunu giderildi — masaüstü uygulaması artık tarayıcıda yetkilendirdikten sonra güvenilir şekilde açılıp girişi tamamlıyor."
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh CN/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect:安装前先看清 APK 内部信息。",
"Dhizuku 静默安装:通过设备所有者权限绕过小米、OPPO、vivo、华为等机型的安装确认弹窗。",
"Obtainium 导入/导出:一键从 Obtainium 迁移你的应用库,也可以随时导出为 Obtainium 格式。",
"从星标添加:列出你 GitHub 星标里发布 APK 的仓库。"
]
},
{
"type": "IMPROVED",
"bullets": [
"未登录用户也能看到「Open Issues」数量和许可证信息了 — 数据来自后端,不消耗任何 GitHub 配额。",
"可完全关闭后台更新检查 — 如果你更喜欢手动检查,这能省电。"
]
},
{
"type": "FIXED",
"bullets": [
"移除液态玻璃效果 — 在深色模式下,透明背景上的图标可能会看不清。整体界面更干净、对比度更高。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh CN/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"按应用忽略更新 — 不想更新的应用,可以单独隐藏其更新提示。",
"跳过指定版本 — 误报的更新提示可以单独跳过;当有更新的版本发布时会再次通知你。",
"通过 Root 静默安装 — Magisk、KernelSU、APatch 用户无需 Shizuku 或 Dhizuku 即可安装。"
]
},
{
"type": "FIXED",
"bullets": [
"从系统设置卸载的应用,现在会立即从已追踪列表中消失。",
"更准确的版本识别 — 数字版本相同但构建元数据不同的发布,不再被误判为'已安装相同版本'。",
"连续更新多个应用现在更可靠了 — 安装会依次进行,系统弹窗不再显示上一个 APK;每次安装后,应用界面的版本也会正确更新。",
"当一个发布同时包含普通版和 F-Droid 版时,自动更新现在会选择正确的 APK — 不再会因此意外安装另一个包名不同的姊妹应用。"
]
},
{
"type": "IMPROVED",
"bullets": [
"Oppo / OnePlus / Realme / 小米 / vivo / Honor 上的后台更新更稳定 — 设置中新增电池优化白名单一键入口,更新任务以加急优先级运行。",
"Android 14+ 的 Dhizuku 静默安装 — 当系统要求确认时,应用现在会自动以无安装来源标识方式重试。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh CN/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-CN/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"全新「发现」标签页 — 为你的平台精选可安装应用的发现信息流。每天刷新,总有新内容;滚动时自动加载更多。",
"全新「排行榜」标签页 — 浏览全店的热门趋势、最新发布和最受欢迎的应用。"
]
},
{
"type": "FIXED",
"bullets": [
"下载应用时现在会自动选择与设备 CPU(如 aarch64)匹配的版本,而不再默认使用更大的通用 APK。",
"修复了 Windows 上的 GitHub 登录 — 在浏览器中授权后,桌面应用现在能可靠地打开并完成登录。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh TW/16.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-TW/16.json)
{
"versionCode": 16,
"versionName": "1.8.1",
"releaseDate": "2026-05-03",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"APK Inspect:安裝前先看清 APK 內部資訊。",
"Dhizuku 靜默安裝:透過裝置所有者許可權繞過小米、OPPO、vivo、華為等機型的安裝確認彈窗。",
"Obtainium 匯入/匯出:一鍵從 Obtainium 遷移你的應用庫,也可以隨時匯出為 Obtainium 格式。",
"從星標新增:列出你 GitHub 星標裡釋出 APK 的倉庫。"
]
},
{
"type": "IMPROVED",
"bullets": [
"未登入使用者也能看到「Open Issues」數量和許可證資訊了 — 資料來自後端,不消耗任何 GitHub 配額。",
"可完全關閉後臺更新檢查 — 如果你更喜歡手動檢查,這能省電。"
]
},
{
"type": "FIXED",
"bullets": [
"移除液態玻璃效果 — 在深色模式下,透明背景上的圖示可能會看不清。整體介面更乾淨、對比度更高。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh TW/17.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-TW/17.json)
{
"versionCode": 17,
"versionName": "1.8.2",
"releaseDate": "2026-05-13",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"按應用忽略更新 — 不想更新的應用,可以單獨隱藏其更新提示。",
"跳過指定版本 — 誤報的更新提示可以單獨跳過;當有更新的版本釋出時會再次通知你。",
"透過 Root 靜默安裝 — Magisk、KernelSU、APatch 使用者無需 Shizuku 或 Dhizuku 即可安裝。"
]
},
{
"type": "FIXED",
"bullets": [
"從系統設定解除安裝的應用,現在會立即從已追蹤列表中消失。",
"更準確的版本識別 — 數字版本相同但構建後設資料不同的釋出,不再被誤判為'已安裝相同版本'。",
"連續更新多個應用現在更可靠了 — 安裝會依次進行,系統彈窗不再顯示上一個 APK;每次安裝後,應用介面的版本也會正確更新。",
"當一個釋出同時包含普通版和 F-Droid 版時,自動更新現在會選擇正確的 APK — 不再會因此意外安裝另一個包名不同的姊妹應用。"
]
},
{
"type": "IMPROVED",
"bullets": [
"Oppo / OnePlus / Realme / 小米 / vivo / Honor 上的後臺更新更穩定 — 設定中新增電池最佳化白名單一鍵入口,更新任務以加急優先順序執行。",
"Android 14+ 的 Dhizuku 靜默安裝 — 當系統要求確認時,應用現在會自動以無安裝來源標識方式重試。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh TW/21.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-TW/21.json)
{
"versionCode": 21,
"versionName": "1.9.2",
"releaseDate": "2026-06-25",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"全新「發現」標籤頁 — 為你的平臺精選可安裝應用的發現資訊流。每天重新整理,總有新內容;滾動時自動載入更多。",
"全新「排行榜」標籤頁 — 瀏覽全店的熱門趨勢、最新發布和最受歡迎的應用。"
]
},
{
"type": "FIXED",
"bullets": [
"下載應用時現在會自動選擇與裝置 CPU(如 aarch64)匹配的版本,而不再預設使用更大的通用 APK。",
"修復了 Windows 上的 GitHub 登入 — 在瀏覽器中授權後,桌面應用現在能可靠地開啟並完成登入。"
]
}
]
}
---
### Core/Presentation/Src/CommonMain/ComposeResources/Files/Whatsnew/Zh TW/22.Json (core/presentation/src/commonMain/composeResources/files/whatsnew/zh-TW/22.json)
{
"versionCode": 22,
"versionName": "1.9.3",
"releaseDate": "2026-06-28",
"showAsSheet": true,
"sections": [
{
"type": "NEW",
"bullets": [
"現已支援繁體中文 — 隨時可在「設定 → 語言」中切換。"
]
}
]
}
---
### Fastlane/Metadata/Android/En US/Full Description (fastlane/metadata/android/en-US/full_description.txt)
Komi Store is an open "app store" for GitHub, Codeberg, Forgejo, and Gitea releases. Discover repositories that ship real installers and keep them updated — no scraping, no waiting on stores.
Browse Trending, Hot Releases, Most Popular, and topic feeds (Privacy, Media, Productivity, Networking, Dev Tools). Search across GitHub or any forge host you trust. Tap an APK and install it — the app handles the rest.
FEATURES
- Multi-forge support — GitHub, Codeberg, Forgejo, Gitea, and any self-hosted instance you add.
- Smart discovery — Trending, Hot Releases, Most Popular, and curated topic categories, platform-aware.
- Tracked installs — link any sideloaded or F-Droid app to its repo and get update notifications.
- Multiple install backends — default Android installer, Shizuku (silent install on Android 11+), Dhizuku, and root via libsu (Magisk / KernelSU / APatch).
- Pinned asset variants — fingerprints the exact APK you picked (universal vs arm64 vs Play) so monorepo updates land on the same flavor every time.
- Skip-release / ignore-updates / advanced asset regex per app.
- Sign in with GitHub via web OAuth (PKCE handoff), device flow, or a Personal Access Token — pick what works for your network.
- Per-host Personal Access Tokens for private repos on any forge.
- Mirror support for restricted networks — fastly.jsdelivr.net plus your own custom mirrors.
- README translation in-app — Google, Youdao, LibreTranslate, DeepL, or Microsoft, your key, your provider.
- Material 3 design with Material You dynamic colors on Android 12+, light / dark / AMOLED themes.
- Obtainium import/export, starred-repo picker, and "Scan GitHub Apps" to attach repos to apps already on your device.
- AES-256-GCM encrypted credentials and preferences via KSafe (hardware-backed Keystore on Android).
- 13 languages — English, Spanish, French, Italian, Polish, Russian, Turkish, Arabic, Hindi, Bengali, Japanese, Korean, Simplified Chinese.
Also available on Desktop (Windows, macOS, Linux) with tablet two-pane layout, fluid content width, persistent window state, and a native dark title bar on Windows 11 and macOS.
Built with Kotlin Multiplatform and Compose Multiplatform. Source on GitHub at kurikomi-labs/komi-store.
---
### Fastlane/Metadata/Android/En US/Short Description (fastlane/metadata/android/en-US/short_description.txt)
App store for GitHub releases - discover and install apps with one click
---
### Feature/Apps/CLAUDE (feature/apps/CLAUDE.md)
# Apps Feature
Installed-apps manager. Lists apps installed through GHS, launches them, checks updates. Android-only in nav (bottom-nav hidden on Desktop).
## Structure
```
feature/apps/
├── domain/repository/AppsRepository.kt
├── data/ AppsRepositoryImpl + di
└── presentation/
├── AppsViewModel / State / Action / Event / Root
├── components/ app item cards, update badges, LinkAppBottomSheet, AdvancedAppSettingsBottomSheet, ApkInspectSheet, import banner
├── import/ # ExternalImportRoot/ViewModel — Obtainium import/export + manual-link
└── starred/ # StarredPickerRoot/ViewModel — APK-shipping subset of user's GitHub stars
```
## Key interface
```kotlin
interface AppsRepository {
suspend fun getApps(): Flow>
suspend fun openApp(installedApp: InstalledApp, onCantLaunchApp: () -> Unit = {})
suspend fun getLatestRelease(owner, repo, includePreReleases = false, sourceHost: String? = null): GithubRelease?
suspend fun fetchRepoInfo(owner, repo, sourceHost: String? = null): GithubRepoInfo?
suspend fun linkAppToRepo(..., sourceHost: String? = null)
/* exportApps / exportObtainium / importApps */
}
```
## Navigation
`GithubStoreGraph.AppsScreen`, `ExternalImportScreen`, `StarredPickerScreen`.
## Notes
- Uses `InstalledAppsRepository` + `SyncInstalledAppsUseCase`. `openApp` via `AppLauncher`. `PackageMonitor` + `Installer` (Android). Data layer injects `ForgejoClientRegistry`; non-null `sourceHost` on `getLatestRelease` / `fetchRepoInfo` / `linkAppToRepo` routes to the Forgejo client (else default GitHub-direct path).
- **`sourceHost` propagation:** `InstalledApp.sourceHost` persisted on link; `AppsAction.OpenAppDetails` / `OpenRepoDetails` + `AppsEvent.NavigateToRepo` carry `sourceHost`; `AppsRoot.onNavigateToRepo` is `(repoId, sourceHost, owner, repo) -> Unit` and routes to `GithubStoreGraph.DetailsScreen(sourceHost = …)`.
- **Multi-source backend match:** `RepoSuggestion` candidates may come from GitHub *or* a Forgejo host; the link sheet displays the source host chip per row so the user picks the right forge variant.
- Sort + search: `AppSortRule` enum (UpdatesFirst default, AlphabeticalAZ, RecentlyAdded, RecentlyUpdated). Persisted in DataStore. Inline search filters appName / packageName.
- Per-app actions: Ignore-updates (silence badge), Skip-this-release (per-tag, auto-clear on next release), Advanced filter (regex on asset names + monorepo fallback), Pin variant (token-set + glob fingerprint), Inspect APK (decoded manifest sheet).
- Link sheet (`LinkAppBottomSheet`) sorts installed apps by `InstallerCategory` (`core/domain`): SIDE_STORE (F-Droid / Obtainium / Aurora / Droid-ify / GHS itself) → SIDELOADED → VENDOR_STORE (Samsung / Huawei / Xiaomi / Oppo / vivo / Honor / Amazon) → PLAY_STORE → SYSTEM_UPDATE. `DeviceApp.installerPackageName` (via `PackageManager.getInstallSourceInfo` / pre-30 fallback) + `isUpdatedSystemApp` (via `FLAG_UPDATED_SYSTEM_APP`) feed the classifier. Each row shows a tonal source chip — F-Droid / Obtainium surfaces first; Samsung Authentication Framework and friends drop to the bottom.
- Auto-update on resume: `OnLifecycleResume` fires `autoCheckForUpdatesIfNeeded` (30-min cooldown) — catches drift after external install while GHS background-killed.
- External import (`import/`): Obtainium JSON import/export with pre-import summary buckets (imported / already-tracked / non-GitHub-skipped); manual-link-only path. **Skip-on-slow-scan:** after `~5s` `state.isSkipAvailable` flips true → user can fire `OnSkipLongScan` to abort the in-flight backend lookup and move on without waiting for the remaining candidates.
- Starred picker (`starred/`): scans signed-in user's GitHub stars, surfaces APK-shipping repos. Resumes mid-scan on rate-limit.
---
### Feature/Auth/CLAUDE (feature/auth/CLAUDE.md)
# Auth Feature
Three GitHub sign-in paths, picked per session: **web OAuth + PKCE + handoff** (primary), **device flow** (fallback), **Personal Access Token paste** (last resort). Works on Android + Desktop.
## Structure
```
feature/auth/
├── domain/repository/AuthenticationRepository.kt # contract + AuthPath, DeviceFlowStart, PollOutcome, WebAuthRegistration, PatRejectedException
├── data/
│ ├── crypto/PkceGenerator.kt # SHA-256 PKCE triplet (state + verifier + challenge)
│ ├── network/GitHubAuthApi.kt # direct + backend-proxied device-flow endpoints
│ ├── network/WebAuthApi.kt # web-OAuth register + handoff consume
│ ├── repository/AuthenticationRepositoryImpl.kt
│ └── di
└── presentation/
├── AuthenticationViewModel / State / Action / Event / Root
├── AuthDeepLinkBus.kt # SharedFlow bridge from app-level deep-link parser to VM
└── components/
```
## Key interface
```kotlin
interface AuthenticationRepository {
val accessTokenFlow: Flow
suspend fun startDeviceFlow(): DeviceFlowStart
suspend fun awaitDeviceToken(start: GithubDeviceStart): GithubDeviceTokenSuccess
suspend fun pollDeviceTokenOnce(deviceCode: String, path: AuthPath): PollOutcome
suspend fun signInWithPat(token: String): Result
suspend fun registerWebAuth(): Result
suspend fun exchangeWebAuthHandoff(handoffId: String): Result
}
enum class AuthPath { Backend, Direct }
```
## Navigation
`GithubStoreGraph.AuthenticationScreen`.
## Web OAuth path (primary)
1. `PkceGenerator.generate()` → `(state, codeVerifier, codeChallenge)` (S256).
2. `WebAuthApi.register(state, codeChallenge, codeVerifier)` → POST `https://github-store.org/auth/register`. Cloudflare Worker stores `(state → {codeVerifier, codeChallenge})` in Workers KV with short TTL and returns `auth_url` (the `github.com/login/oauth/authorize?…` URL).
3. VM opens `auth_url` in user's browser via `BrowserHelper`.
4. User authorizes on GitHub. GitHub redirects to `https://github-store.org/auth/callback?code=…&state=…`.
5. Worker re-validates `state`, exchanges `code` against `api.github-store.org` (backend posts to GitHub `/oauth/access_token` with the stored verifier), backend writes `(handoffId → access_token)` to Postgres with 60s TTL.
6. Worker redirects browser to `githubstore://auth?h=` (custom scheme picked up by app via OS deep link).
7. App-level `DeepLinkParser` routes the URI through `AuthDeepLinkBus`. VM calls `exchangeWebAuthHandoff(handoffId)` → `WebAuthApi.consumeHandoff` → POST `api.github-store.org/v1/oauth/handoff/` (atomic `DELETE…RETURNING` — single-use). Token lands in `TokenStore`.
Custom scheme is public — any app can fire `githubstore://auth?…`. The `state` parameter and 60s server-side TTL are the integrity guards; without a live KV entry the handoff is a no-op.
## Device flow path (fallback)
Used when web flow can't complete (browser unreachable, deep link not registered, user explicitly picks "Use device code instead").
- Primary sub-path: backend proxy `/v1/auth/device/start` + `/poll` on `api.github-store.org` for networks throttling `github.com` (China, corporate filters).
- Each session picks one `AuthPath` (`Backend` | `Direct`), persists in `SavedStateHandle`. Only escalates `Backend → Direct` on infra errors (timeout / 5xx / 429-without-Retry-After). HTTP 4xx and GitHub negative 200-bodies (`authorization_pending`, `slow_down`, `access_denied`, `expired_token`, `bad_verification_code`) are real answers — never trigger fallback.
- Backend rate limits hard: 10 starts/hr, 200 polls/hr per IP. Don't add retry loops on top of Ktor's `HttpRequestRetry(maxRetries = 2)`.
- Backend responses carry `X-Request-ID` — `GitHubAuthApi` embeds it in error messages via `asRequestIdTag()` for cross-log correlation.
## PAT path (last resort)
`signInWithPat(token)`:
1. Client-side format check (rejects obvious paste-errors — needs `ghp_` / `github_pat_` prefix).
2. Network check against GitHub `/user`. 401 → `PatRejectedException(BadCredentials)`, 403 → `InsufficientScope`, other non-2xx → `Other(statusCode)`. On reject the sheet stays open.
3. If GitHub is unreachable (timeout/DNS/block) the token persists optimistically — the whole reason this path exists is for users who can't reach GitHub reliably. A bad-but-unreachable token surfaces a 401 on the first authenticated call.
## Notes
- Token stored via `TokenStore` (DataStore-backed). `accessTokenFlow` observed app-wide.
- `GITHUB_CLIENT_ID` in `local.properties` for builds — must match the OAuth App registered on the backend and used by the Worker.
- Endpoints: `WEB_ORIGIN = https://github-store.org`, `BACKEND_ORIGIN = https://api.github-store.org`. Constants in `core/data/network/BackendEndpoints.kt`.
- Android deep-link filters in `composeApp/src/androidMain/AndroidManifest.xml`: scheme `githubstore`, hosts `auth`, `callback`, `repo`, `apps`. Desktop registers the protocol via `DesktopDeepLink` on Win/Linux (macOS uses the bundle Info.plist `CFBundleURLTypes`).
---
### Feature/Details/CLAUDE (feature/details/CLAUDE.md)
# Details Feature
Repository detail screen — owner, stats, releases with download/install, readme (with translation), per-app install/update flow. Most complex feature.
## Structure
```
feature/details/
├── domain/ # DetailsRepository, TranslationRepository; ReleaseCategory, RepoStats, SupportedLanguage, TranslationResult
├── data/ # impls + ReadmeLocalizationHelper, preprocessMarkdown
└── presentation/
├── DetailsViewModel.kt / State / Action / Event / Root
├── model/ # DownloadStage, InstallLogItem, LogResult, ShowDowngradeWarning, SupportedLanguages, TranslationState
├── components/
│ ├── AppHeader, ReleaseAssetsPicker, VersionPicker, VersionTypePicker, SmartInstallButton, InspectApkButton, ApkInspectSheet, LanguagePicker, TranslationControls, StatItem
│ └── sections/ About, Header, Logs, Owner, ReportIssue, Stats, WhatsNew, ReleaseChannel
├── states/ErrorState
└── utils/ # MarkdownImageTransformer, MarkdownUtils, SystemArchitecture, LocalTopbarLiquidState, LogResultAsText
```
## Navigation
`GithubStoreGraph.DetailsScreen(repositoryId, owner, repo, isComingFromUpdate, sourceHost)`. By ID or owner+name (deep links use latter; `repositoryId == -1` falls back to owner+name lookup). `sourceHost` non-null routes all `DetailsRepository` calls through `ForgejoClientRegistry` (Codeberg / Forgejo / custom forge).
## Notes
- Readme localized via `ReadmeLocalizationHelper`; markdown via `multiplatform-markdown-renderer` + `MarkdownImageTransformer`. Translation via `TranslationRepository` + `LanguagePicker`. `TranslationProvider` enum = `GOOGLE` / `YOUDAO` / `LIBRE_TRANSLATE` / `DEEPL` / `MICROSOFT`.
- Download stages: `DownloadStage` idle→downloading→installing→done. `SmartInstallButton` adapts to install state. Downgrade warning before installing older version.
- Injects (lots): `DetailsRepository`, `TranslationRepository`, `FavouritesRepository`, `StarredRepository`, `InstalledAppsRepository`, `SeenReposRepository`, `TweaksRepository`, `TelemetryRepository`, `ExternalImportRepository`, `AuthenticationState`, `ProfileRepository`, `Downloader`, `Installer`, `PackageMonitor`, `SystemInstallSerializer`, `BrowserHelper`, `ShareManager`, `Platform`, `SyncInstalledAppsUseCase`, `InstallationManager`, `AttestationVerifier`, `DownloadOrchestrator`, `ApkInspector`, `GitHubStoreLogger`. Data layer additionally injects `ForgejoClientRegistry`.
- Android installer paths: Default / Shizuku / Dhizuku / Root. Root via raw `su` (`RootServiceManager`). Dhizuku 14+ retries without installer attribution.
- **Multi-OS picker (E15):** `ReleaseAssetsItemsPicker` toggle flips `TweaksRepository.showAllPlatforms`. ON → assets group by `assetPlatformOf` into `PlatformSectionCard`s with "Your device"/"For transfer" chips. Non-current asset → `OnDownloadForTransfer` → `BrowserHelper.openUrl`.
- **Coachmarks:** APK Inspect button pulse + ReleaseChannel chip Popup. One-shot via `TweaksRepository.get*CoachmarkShown`.
- **Self-owned ✓ badge (E20):** `AppHeader` ✓ next to owner login when `state.isCurrentUserOwner`. Reactive via `combine(profileRepo.getUser(), state.repository.owner.login)`.
- **Skip release (E542):** per-app `skippedReleaseTag` on `InstalledApp`. `SmartInstallButton` suppresses CTA; auto-clears on strictly-newer release.
- **Forgejo / Codeberg branch:** `DetailsRepositoryImpl.getRepositoryByOwnerAndName / getAllReleases / getReadme / getRepoStats / getLatestPublishedRelease` accept `sourceHost: String? = null`. Non-null → `ForgejoApiClient` direct call (no backend mediator). README from `/contents/README.md?ref={branch}` (Forgejo lacks `/readme`); license sniffed from `/contents/LICENSE` via SPDX regex; downloads aggregated by summing asset `download_count`. CRLF release bodies normalized so GFM tables render. Foreign-source `getUserProfile` skipped (GitHub-only). `AppHeader` avatar falls back to `repository.owner.avatarUrl` when profile null.
- **Multi-flavor primary picker (#638):** `pickPrimaryInstalledApp` prefers asset-filter match → `isUpdateAvailable=false` variant → `first()`. Prevents false "Update" CTA when a project ships multiple packages (e.g. generic + Play APK) and only one variant is current.
- **Content width:** `LocalContentWidth` (`COMPACT` 680dp default, `WIDE` 960dp, `EXTRA_WIDE` fills window). Set in `Tweaks → Appearance` (desktop). Outer Box's `Modifier.scrollable(state=listState, reverseDirection=true, enabled = !ANDROID)` forwards mouse-wheel events from empty side gutters to the LazyColumn — gated to non-Android to avoid double scrollable contending with LazyColumn touch.
- **Markdown perf:** Chunked progressive rendering (`splitMarkdownIntoChunks`, ~4000 chars). Pre-processing (theme-aware images + `separateAdjacentImageLinks`) on `Dispatchers.Default`. `onAction` lambda hoisted via `remember`; `MarkdownComponents` memoized; `TranslationState @Immutable`. Together kills download-progress-driven recomp storms.
- **Markdown image link awareness:** `LinkAwareMarkdownImage` walks `ASTNode.parent` for `INLINE_LINK`, makes badge images clickable to outer href. `MarkdownImageTransformer` adds browser-like User-Agent + accept header to bypass CDN hotlink protection on common badge services.
---
### Feature/Dev Profile/CLAUDE (feature/dev-profile/CLAUDE.md)
# Dev Profile Feature
GitHub user/dev profile view — avatar, bio, stats, their repos with filter/sort, followers/following. Reached from any repository card.
## Structure
```
feature/dev-profile/
├── domain/ # DeveloperProfileRepository; DeveloperProfile, DeveloperRepository, RepoFilterType (All/Sources/Forks/…), RepoSortType (Stars/Name/Updated/…)
├── data/ # impl + dto + mappers + di
└── presentation/
├── DeveloperProfileViewModel / State / Action / Event / Root
└── components/ profile header, repo list, filter controls
```
## Key interface
```kotlin
interface DeveloperProfileRepository {
suspend fun getDeveloperProfile(username: String): Result
suspend fun getDeveloperRepositories(username: String): Result>
}
```
## Navigation
`GithubStoreGraph.DeveloperProfileScreen(username: String)`.
## Notes
- Profile + repos fetched in parallel.
- Client-side filter/sort.
- Both API calls return `Result`.
- Reached from cards throughout app (home/search/details/favourites/starred).
---
### Feature/Favourites/CLAUDE (feature/favourites/CLAUDE.md)
# Favourites Feature
Local saved favorites view. **Presentation-only** — uses `FavouritesRepository` from `core/domain` directly.
## Structure
```
feature/favourites/presentation/
├── FavouritesViewModel / State / Action / Root
├── model/FavouriteRepository
├── mappers/FavouriteRepositoryMapper
└── components/FavouriteRepositoryItem
```
## Deps
- `FavouritesRepository` (core/domain) — CRUD
- `ProfileRepository` (feature/profile/domain) — E20 self-owned badge
- Local Room (`FavoriteRepoDao` in core/data)
## Navigation
`GithubStoreGraph.FavouritesScreen`.
## Notes
- No network. All local Room.
- Adding to favourites happens elsewhere (home/details/search). This module displays + removes.
- Inline search bar (E562) when list non-empty — filters by name/owner/description/language client-side.
- `FavouriteRepository.isCurrentUserOwner` set when signed-in user owns the repo (E20).
- Koin module registered in `composeApp/.../app/di/ViewModelsModule.kt` (no `data/di/`).
---
### Feature/Home/CLAUDE (feature/home/CLAUDE.md)
# Home Feature
Main discovery — Trending, Hot Releases, Most Popular. Infinite-scroll pagination. Integrates installed-app / favourite / starred status badges.
## Structure
```
feature/home/
├── domain/ # HomeRepository + HomeCategory (TRENDING / HOT_RELEASE / MOST_POPULAR), TopicCategory
├── data/ # HomeRepositoryImpl, CachedRepositoriesDataSource (per-category 7-day TTL), dto, mappers, di
└── presentation/
├── HomeViewModel / State / Action / Event / Root
├── components/HomeFilterChips
├── locals/LocalHomeTopBarLiquid
└── utils/HomeCategoryMapper
```
## Key interface
```kotlin
interface HomeRepository {
fun getTrendingRepositories(page: Int): Flow
fun getHotReleaseRepositories(page: Int): Flow
fun getMostPopular(page: Int): Flow
}
```
## Navigation
`GithubStoreGraph.ChartsScreen` (bottom-nav label "Top Charts"). The `ExploreScreen` route renders the feed feature, not this one.
## VM injects
`HomeRepository`, `InstalledAppsRepository`, `Platform`, `SyncInstalledAppsUseCase`, `FavouritesRepository`, `StarredRepository`, `GitHubStoreLogger`, `ShareManager`, `TweaksRepository`, `SeenReposRepository`, `HiddenReposRepository`, `ProfileRepository`.
## Notes
- `Semaphore` in `HomeRepositoryImpl` for concurrent request control. 7-day per-category cache. Pagination via `nextPageIndex`, dedupe by `fullName`.
- `HomeRoot.visibleRepos` derives display list — filters by `hiddenRepoIds` (E11) and `seenRepoIds` when `isHideSeenEnabled`.
- Apps section in bottom nav: `Platform.ANDROID` only.
- Long-press on `RepositoryCard` opens `RepositoryActionsBottomSheet` (Share / Open on GitHub / Mark seen / Hide).
- `DiscoveryRepositoryUi.isCurrentUserOwner` flipped by `observeCurrentUser` (E20).
- State uses `onStart` + `stateIn(WhileSubscribed)`.
---
### Feature/Profile/CLAUDE (feature/profile/CLAUDE.md)
# Profile Feature
Account-level — GitHub user profile, login/logout, version info. **Settings live in `feature/tweaks/`** — this module narrow on purpose. Owns account identity + exposes `ProfileRepository.getUser()` to other features (home/search/details/starred/favourites/tweaks/dev-profile consume it for E20 self-owned badge and account-aware flows).
## Structure
```
feature/profile/
├── domain/ # ProfileRepository, UserProfile
├── data/ # ProfileRepositoryImpl, UserProfileMappers
└── presentation/
├── ProfileViewModel / State / Action / Event / Root
├── model/ProxyType (legacy — proxy lives in tweaks now)
└── components/ LogoutDialog, SectionText, sections/{Account, AccountSection, ProfileSection}
```
## Key interface
```kotlin
interface ProfileRepository {
val isUserLoggedIn: Flow
fun getUser(): Flow
fun getVersionName(): String
suspend fun logout()
fun observeCacheSize(): Flow
suspend fun clearCache()
}
```
## Navigation
`GithubStoreGraph.ProfileScreen`.
## Notes
- `getUser()` cached via `CacheManager` key `profile:me`. Invalidates on logout.
- "Settings" tap → `TweaksScreen`. Don't add settings here.
- VM injects: `ProfileRepository`, `Platform`.
---
### Feature/Recently Viewed/CLAUDE (feature/recently-viewed/CLAUDE.md)
# Recently Viewed Feature
Local "recently viewed" history — every repo whose Details screen was opened. **Presentation-only**, backed by `SeenReposRepository` (same pipeline that drives "Hide seen" filter on Home/Search).
## Structure
```
feature/recently-viewed/presentation/
├── RecentlyViewedViewModel / State / Action / Root
├── model/RecentlyViewedRepo, mappers/RecentlyViewedRepoMapper
└── components/RecentlyViewedItem
```
## Navigation
`GithubStoreGraph.RecentlyViewedScreen`.
## Notes
- Visited timestamps come from `seenRepoDao.insert(...)` calls in `DetailsViewModel` on screen open.
- No network. `seenReposRepository.clearAll()` wipes table; `removeFromHistory(repoId)` for single-row.
- Koin in `composeApp/.../app/di/ViewModelsModule.kt` (no `data/di/`).
---
### Feature/Search/CLAUDE (feature/search/CLAUDE.md)
# Search Feature
Repo search with platform / language / sort filters. Paginated results.
## Structure
```
feature/search/
├── domain/ # SearchRepository; SearchPlatform (All/Android/Macos/Windows/Linux), ProgrammingLanguage, SortBy
├── data/ # SearchRepositoryImpl + dto + mappers + di
└── presentation/
├── SearchViewModel / State / Action / Event / Root
└── components/ filter chips, ClipboardLinkBanner, etc.
```
## Key interface
```kotlin
interface SearchRepository {
fun searchRepositories(
query: String,
platform: DiscoveryPlatform,
language: ProgrammingLanguage,
sortBy: SortBy,
sortOrder: SortOrder,
page: Int,
source: SearchSource = SearchSource.GitHub,
): Flow
suspend fun exploreFromGithub(query, platform, page): ExploreResult
}
sealed interface SearchSource { object GitHub; data class Forgejo(host); /* Codeberg = Forgejo("codeberg.org") */ }
```
## Navigation
`GithubStoreGraph.SearchScreen`.
## Notes
- Platform filter → GitHub topic search (e.g. `android` topic). Language filter → `language:` qualifier. Debounce/throttle on queries.
- **Source toggle (`SearchSourceUi`):** UI surfaces `GitHub`, `Codeberg`, and per-user-added `Custom(host)` chips (from `TweaksRepository.customForgeHosts`). `state.selectedSource` → repository's `source: SearchSource` param. Forgejo branch in `SearchRepositoryImpl` hits `ForgejoClientRegistry.clientFor(host)` (`/repos/search`) — no backend mediator.
- Injects: `SearchRepository`, `InstalledAppsRepository`, `SyncInstalledAppsUseCase`, `FavouritesRepository`, `StarredRepository`, `SeenReposRepository`, `HiddenReposRepository`, `TweaksRepository`, `ProfileRepository`, `TelemetryRepository`, `SearchHistoryRepository`, `ShareManager`, `ClipboardHelper`, `Platform`, `GitHubStoreLogger`. Data layer additionally injects `ForgejoClientRegistry`.
- `computeVisibleRepos` filters `state.repositories` at render time by `hiddenRepoIds` AND (when `isHideSeenEnabled`) `seenRepoIds`. Unhide restores without re-fetch.
- Empty-grid-after-Hide-seen banner offers one-tap reset (issue #574) → `OnDisableHideSeenForResults`.
- Long-press card → shared `RepositoryActionsBottomSheet`.
- `DiscoveryRepositoryUi.isCurrentUserOwner` flipped by `observeCurrentUser` (E20).
- Clipboard auto-detect surfaces GitHub URLs from clipboard as a dismissible banner.
---
### Feature/Starred/CLAUDE (feature/starred/CLAUDE.md)
# Starred Feature
Locally cached view of user's starred repos. **Presentation-only** — uses `StarredRepository` from `core/domain` directly.
## Structure
```
feature/starred/presentation/
├── StarredReposViewModel / State / Action / Root
├── model/StarredRepositoryUi
├── mappers/StarredRepoToUiMapper
├── utils/TimeFormatUtils
└── components/StarredRepositoryItem
```
## Deps
- `StarredRepository`, `FavouritesRepository`, `AuthenticationState` (core/domain)
- `ProfileRepository` (feature/profile/domain) — current user login for E20 self-owned badge
- Local Room (`StarredRepoDao` in core/data)
## Navigation
`GithubStoreGraph.StarredReposScreen`.
## Notes
- Periodic sync against GitHub's `/user/starred` (gated on `isAuthenticated`). Local Room mirror is the read source.
- UI model `StarredRepositoryUi` mapped from domain `StarredRepository`.
- Starring happens elsewhere (home/details/search). This module displays + removes.
- Inline search bar (E562) when list non-empty — filters by name/owner/description/language client-side. `OnRefresh` clears active query so refreshed list isn't masked behind stale filter.
- `StarredRepositoryUi.isCurrentUserOwner` set when signed-in user owns the repo (E20).
- Koin module registered in `composeApp/.../app/di/ViewModelsModule.kt` (no `data/di/`).
---
### Feature/Tweaks/CLAUDE (feature/tweaks/CLAUDE.md)
# Tweaks Feature
Single home for every app-level setting. Update prefs, installer choice (Default / Shizuku / Dhizuku / Root), telemetry, translation, mirror, feedback, hidden + skipped list managers. Absorbs settings half of former `feature/profile/`.
## Structure
```
feature/tweaks/presentation/
├── TweaksViewModel / State / Action / Event / Root, RestartApp
├── components/
│ ├── sections/ Account, Appearance, Installation, Language, Network, Others, Translation, SettingsSection
│ └── ToggleSettingCard, ClearDownloadsDialog, SectionText, CustomForgesDialog
├── feedback/ # FeedbackViewModel + sheet
├── hidden/ # HiddenRepositoriesRoot — Tweaks → Updates → Hidden repos
├── skipped/ # SkippedUpdatesRoot — Tweaks → Updates → Skipped updates
├── hosttokens/ # HostTokensRoot/ViewModel — Tweaks → Access Tokens (per-host PATs)
├── mirror/ # MirrorPickerRoot — Tweaks → Network → Mirror picker
└── model/ # ProxyScopeFormState, ProxyType
```
## Sub-screen VMs (registered in `composeApp/.../app/di/ViewModelsModule.kt`)
`SkippedUpdatesViewModel` (unskip via `InstalledAppsRepository.setSkippedReleaseTag`), `HiddenRepositoriesViewModel` (unhide / unhide-all via `HiddenReposRepository`), `HostTokensViewModel` (CRUD on `HostTokenRepository`), `FeedbackViewModel`, `AutoSuggestMirrorViewModel`, `MirrorPickerViewModel`.
## Navigation
`TweaksScreen`, `SkippedUpdatesScreen`, `HiddenRepositoriesScreen`, `HostTokensScreen`, `MirrorPickerScreen`.
## Notes
- TweaksViewModel injects: `TweaksRepository`, `ThemesRepository`, `ProxyRepository`, `InstalledAppsRepository`, `ProfileRepository`, `InstallerStatusProvider`, `TelemetryRepository`, `Platform`, `BatteryOptimizationManager` (Android), `GitHubStoreLogger`.
- One-shot coachmark flags in `TweaksRepository` (`apk_inspect_coachmark_shown`, `channel_chip_coachmark_shown`). Once persisted true, never re-shown.
- `include_pre_releases` pref read by `InstallationManagerImpl` to seed new install's `InstalledApp.includePreReleases`. Existing rows keep per-app value.
- `show_all_platforms` pref drives cross-platform asset section in Details.
- Mirror picker gated on user locale (suggested in throttled regions).
- **Appearance → Content width (desktop):** `ContentWidthCard` picks `ContentWidth` (`COMPACT` / `WIDE` / `EXTRA_WIDE`); written via `OnContentWidthSelected` action; consumed by `LocalContentWidth` in Details.
- **Network → Custom forges:** `CustomForgesDialog` (opened via `OnOpenCustomForgesDialog`) edits `state.customForgeHosts` (persisted via `TweaksRepository`). Hosts surface in `RepositoryUrlParser` + power `SearchSourceUi.Custom` chips + register Ktor clients in `ForgejoClientRegistry`.
- **Access Tokens (`HostTokensScreen`):** sub-screen lists / adds / edits / deletes per-host PATs in `HostTokenRepository` (AES-256-GCM via KSafe). Token surfaces via `HostTokenInterceptor` on matched host (`api.github.com → github.com` mapped through `HostNames.apiHostToTokenHost`).
- **Translation section:** `AutoTranslateCard` toggles `OnAutoTranslateEnabledToggle` + picks target via `OnAutoTranslateTargetSelected`. Per-provider credential forms — `LibreTranslateCredentialsForm` (base URL + API key, defaults to `translate.disroot.org` mirror when blank), `MicrosoftCredentialsForm` (key + region; Azure portal deep-link); DeepL key field auto-routes `:fx` suffix to free endpoint. All credentials persisted via `TweaksRepository` (KSafe-encrypted), visibility toggles per field.
- `RestartApp.kt` applies locale change (persist tag, restart MainActivity / DesktopApp).
---
### Packaging/Flatpak/README (packaging/flatpak/README.md)
# Flatpak Packaging for Komi Store
## Sandbox limitations
The sandbox can't exec or install host binaries, so the Flatpak is browse-and-download only: files land in `~/Downloads` (`--filesystem=xdg-download:rw`); the user installs them manually outside.
Don't add `--filesystem=host` or `--talk-name=org.freedesktop.Flatpak` without a tested host-spawn path — Flathub rejects unjustified host access. For install + auto-update, use the AppImage / deb / rpm / Arch builds.
## Prerequisites
Install Flatpak and the build tools:
```bash
# Fedora
sudo dnf install flatpak flatpak-builder
# Ubuntu/Debian
sudo apt install flatpak flatpak-builder
# Arch
sudo pacman -S flatpak flatpak-builder
```
Install the required runtimes:
```bash
flatpak install flathub org.freedesktop.Platform//24.08
flatpak install flathub org.freedesktop.Sdk//24.08
flatpak install flathub org.freedesktop.Sdk.Extension.openjdk21//24.08
```
## Setup (One-Time)
### 1. Generate the offline dependency sources
Offline builds need every Maven/Gradle artifact pre-pinned. There are **two**
source files, each from a different generator — they cover what the other can't:
```bash
# a) project deps -> flatpak-sources.json
rm -rf ~/.gradle/caches # avoid pinning stale versions
./gradlew :composeApp:packageUberJarForCurrentOS --no-configuration-cache # populate cache
python3 packaging/flatpak/generate-all-sources.py # scan cache + auto-verify
# b) build-logic classpath -> flatpak-sources-convention.json
./gradlew -p build-logic :convention:flatpakGradleGenerator --no-configuration-cache
python3 packaging/flatpak/verify-sources.py packaging/flatpak/flatpak-sources-convention.json
```
Why two: the root `flatpakGradleGenerator` plugin under-captures the KMP
multiplatform graph, so the project half uses the cache-scanning
`generate-all-sources.py`. build-logic is a plain JVM build, so its **own** plugin
task captures its classpath correctly — including buildscript transitives like
`gson` that the project cache-scan never sees (and it downloads the jars while
resolving). The manifest lists both files.
Never commit a sources file that fails `verify-sources.py` — every pinned URL
must serve its recorded sha512. `generate-all-sources.py` runs that check
automatically and aborts on any mismatch.
### 2. Verify SHA256 hashes
The manifest uses pre-computed SHA256 hashes. To verify or update them:
```bash
# Gradle distribution
curl -sL https://services.gradle.org/distributions/gradle-8.14.3-bin.zip | sha256sum
# JBR x64 (check latest at https://github.com/JetBrains/JetBrainsRuntime/releases)
curl -sL https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-x64-b1163.105.tar.gz | sha256sum
# JBR aarch64
curl -sL https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-aarch64-b1163.105.tar.gz | sha256sum
```
### 3. Update screenshot URLs
Edit `com.kurikomi.komistore.metainfo.xml` to point to hosted screenshot images.
Flathub requires at least one screenshot with a publicly accessible URL.
## Building Locally
Flatpak builds run on Linux only (`flatpak-builder` is not available on macOS/Windows).
```bash
cd packaging/flatpak
# For a local test build, temporarily swap the manifest's git source for a local dir:
# - type: dir
# path: ../../
# (Flathub itself requires the pinned git source — revert before submitting.)
# Build
flatpak-builder --force-clean build-dir com.kurikomi.komistore.yml
# Test run
flatpak-builder --run build-dir com.kurikomi.komistore.yml komistore
# Install locally
flatpak-builder --user --install --force-clean build-dir com.kurikomi.komistore.yml
```
## Validating
```bash
# Validate AppStream metainfo
flatpak run org.freedesktop.appstream-glib validate com.kurikomi.komistore.metainfo.xml
# Lint manifest (requires org.flatpak.Builder)
flatpak run --command=flatpak-builder-lint org.flatpak.Builder manifest com.kurikomi.komistore.yml
```
## Publishing to Flathub
Prerequisites:
- **Domain verification.** The app ID `com.kurikomi.komistore` is domain-based, so
`kurikomi.com` must be reachable over HTTPS and host a verification token at
`https://kurikomi.com/.well-known/org.flathub.VerifiedApps.txt` (see Flathub docs).
- **A real release tag.** Set the manifest's `commit:` to the SHA that `v1.9.2` points
to. Flathub rejects a git source without a pinned commit.
Steps:
1. Fork `https://github.com/flathub/flathub` (do **not** copy only the master branch).
2. Clone the `new-pr` branch and create a feature branch off it:
`git clone --branch=new-pr git@github.com:/flathub.git && git checkout -b komistore new-pr`
3. Copy the manifest **and all three source JSONs** to the repo root:
`com.kurikomi.komistore.yml`, `flatpak-sources.json`,
`flatpak-sources-convention.json`, `flatpak-sources-manual.json`.
(The desktop entry, metainfo, launcher, and `disable-android` script are pulled
from the git source at build time, so they do not need copying.)
4. Open a PR with base branch **`new-pr`**, titled `Add com.kurikomi.komistore`.
5. Reviewers / the bot trigger test builds. Address any lint or build feedback.
6. After approval, you get write access to `flathub/com.kurikomi.komistore`.
## File Reference
| File | Purpose |
|------|---------|
| `com.kurikomi.komistore.yml` | Flatpak build manifest |
| `com.kurikomi.komistore.desktop` | Desktop launcher entry |
| `com.kurikomi.komistore.metainfo.xml` | AppStream metadata for Flathub listing |
| `komistore.sh` | Shell launcher (invokes `java -jar` with bundled JRE) |
| `disable-android-for-flatpak.sh` | Strips Android targets for sandbox build |
| `flatpak-sources.json` | Pre-downloaded Gradle dependencies (generated) |
---
### Packaging/Flatpak/Com.Kurikomi.Komistore.Yml (packaging/flatpak/com.kurikomi.komistore.yml)
app-id: com.kurikomi.komistore
runtime: org.freedesktop.Platform
runtime-version: '24.08'
sdk: org.freedesktop.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.openjdk21
command: komistore
finish-args:
# Network access for GitHub API calls and downloading releases
- --share=network
# Display support — X11 required (Compose/Skiko doesn't support native Wayland yet)
# On Wayland desktops this uses XWayland, available on all major distros
- --socket=x11
- --share=ipc
# GPU acceleration for Compose rendering
- --device=dri
# Download directory access for APK/release downloads
- --filesystem=xdg-download:rw
modules:
# Module 1: Bundle JetBrains Runtime (JBR) 21 for optimal Compose Desktop rendering
# Using plain jbr (no JCEF) — app doesn't use embedded Chromium
- name: jbr
buildsystem: simple
build-commands:
- mkdir -p /app/jre
- tar xzf jbr-*.tar.gz -C /app/jre --strip-components=1
sources:
# x86_64
- type: file
url: https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-x64-b1163.105.tar.gz
sha256: b6a3b13451d296140727bbde9325dd9ee422e2e9b2c6a9378f346f1b8d1111bc
only-arches:
- x86_64
# aarch64
- type: file
url: https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-aarch64-b1163.105.tar.gz
sha256: 38804f526d869f5a9c49e9b90c04edcbc918b41e8e43264e5d5076d352a959bc
only-arches:
- aarch64
# Module 2: Build and install Komi Store
# (internal module name kept as `githubstore` — the /run/build/githubstore/
# offline-repo paths below depend on it; renaming would break the offline build)
- name: githubstore
buildsystem: simple
build-options:
append-path: /usr/lib/sdk/openjdk21/bin
env:
JAVA_HOME: /usr/lib/sdk/openjdk21
GRADLE_USER_HOME: /run/build/githubstore/.gradle
build-commands:
# Use local Gradle distribution (no network needed)
- sed -i 's|distributionUrl=.*|distributionUrl=gradle-bin.zip|' gradle/wrapper/gradle-wrapper.properties
# Rewrite settings.gradle.kts files to use offline Maven repository
- |
python3 -c "
# 1. Rewrite root settings.gradle.kts
lines = open('settings.gradle.kts').readlines()
includes = [l for l in lines if l.strip().startswith('include(')]
with open('settings.gradle.kts', 'w') as f:
f.write('rootProject.name = \"GithubStore\"\n')
f.write('enableFeaturePreview(\"TYPESAFE_PROJECT_ACCESSORS\")\n\n')
f.write('pluginManagement {\n')
f.write(' includeBuild(\"build-logic\")\n')
f.write(' repositories {\n')
f.write(' maven { url = uri(\"/run/build/githubstore/offline-repository\") }\n')
f.write(' }\n')
f.write('}\n\n')
f.write('dependencyResolutionManagement {\n')
f.write(' repositories {\n')
f.write(' maven { url = uri(\"/run/build/githubstore/offline-repository\") }\n')
f.write(' }\n')
f.write('}\n\n')
# foojay-resolver-convention plugin removed — not needed in Flatpak
# (JAVA_HOME is set explicitly, no toolchain auto-download)
for inc in includes:
f.write(inc)
print('Rewrote root settings.gradle.kts for offline build')
# 2. Rewrite build-logic/settings.gradle.kts
with open('build-logic/settings.gradle.kts', 'w') as f:
f.write('@file:Suppress(\"UnstableApiUsage\")\n\n')
f.write('rootProject.name = \"build-logic\"\n\n')
f.write('pluginManagement {\n')
f.write(' repositories {\n')
f.write(' maven { url = uri(\"/run/build/githubstore/offline-repository\") }\n')
f.write(' }\n')
f.write('}\n\n')
f.write('dependencyResolutionManagement {\n')
f.write(' repositories {\n')
f.write(' maven { url = uri(\"/run/build/githubstore/offline-repository\") }\n')
f.write(' }\n\n')
f.write(' versionCatalogs {\n')
f.write(' create(\"libs\") {\n')
f.write(' from(files(\"../gradle/libs.versions.toml\"))\n')
f.write(' }\n')
f.write(' }\n')
f.write('}\n\n')
f.write('include(\":convention\")\n')
print('Rewrote build-logic/settings.gradle.kts for offline build')
"
# Disable Android targets (no Android SDK in Flatpak sandbox)
- bash packaging/flatpak/disable-android-for-flatpak.sh
# Build uber JAR — all deps resolved from offline-repository (local file:// Maven repo,
# no network needed even without --offline flag since sandbox has no network access)
- ./gradlew :composeApp:packageUberJarForCurrentOS
--no-daemon
--no-configuration-cache
-Dorg.gradle.jvmargs="-Xmx6g -XX:MaxMetaspaceSize=2g"
-Dorg.gradle.parallel=false
# Install the JAR
- install -Dm644 "$(find composeApp/build/compose/jars/ -name '*.jar' -type f | head -1)"
/app/lib/komistore.jar
# Install launcher script
- install -Dm755 packaging/flatpak/komistore.sh /app/bin/komistore
# Install desktop entry
- install -Dm644 packaging/flatpak/com.kurikomi.komistore.desktop
/app/share/applications/com.kurikomi.komistore.desktop
# Install AppStream metainfo
- install -Dm644 packaging/flatpak/com.kurikomi.komistore.metainfo.xml
/app/share/metainfo/com.kurikomi.komistore.metainfo.xml
# Install icon (512x512)
- install -Dm644 composeApp/src/jvmMain/resources/logo/app_icon.png
/app/share/icons/hicolor/512x512/apps/com.kurikomi.komistore.png
sources:
# Flathub requires a pinned git source — no local dirs, no floating refs.
# Set `commit` to the exact SHA that tag v1.9.2 points to before submitting
# (flatpak-builder-lint rejects a git source without a commit).
# Pinned commit (Flathub requires a fixed ref — no branches). Add a
# `tag:` line above `commit:` once a release tag includes these files.
- type: git
url: https://github.com/kurikomi-labs/komi-store.git
commit: f46e709c596e6579964e1b9ea5fcdc91f7497ec3
# Gradle distribution (referenced by gradle-wrapper.properties after sed patch)
- type: file
url: https://services.gradle.org/distributions/gradle-8.14.3-bin.zip
sha256: bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
dest: gradle/wrapper
dest-filename: gradle-bin.zip
# Pre-downloaded Gradle/Maven dependencies for offline build.
# flatpak-sources.json = project deps (generate-all-sources.py)
# flatpak-sources-convention.json = build-logic classpath, incl buildscript
# transitives (e.g. gson) the cache scan can't see. Produced by build-logic's
# own task: ./gradlew -p build-logic :convention:flatpakGradleGenerator
- flatpak-sources.json
- flatpak-sources-convention.json
# Hand-pinned artifacts neither generator captures: evicted-version POMs
# (e.g. gson 2.8.9, declared by kotlin-build-statistics but conflict-upgraded)
# that offline resolution still needs to evaluate the version conflict.
- flatpak-sources-manual.json
---
### Packaging/Flatpak/Flatpak Sources Manual.Json (packaging/flatpak/flatpak-sources-manual.json)
[
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.9/gson-2.8.9.pom",
"sha512": "1b32f3407e7bf92341b0223113e807a4bea7da2bbc0485eb6d5ba090b77df4af3f9e547a5181ef1e440e011257b1ea37e1c304c8524ca6a3609e70be1fda960b",
"dest": "offline-repository/com/google/code/gson/gson/2.8.9",
"dest-filename": "gson-2.8.9.pom"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.9/gson-2.8.9.jar",
"sha512": "46501e4dd34c9a6f33ff63aeeec45b049579365c5273490e5dfd5ea4effaeced907d0fc728204c619aa136e867ad826204582ff9ba3080d06693c1c675c8473f",
"dest": "offline-repository/com/google/code/gson/gson/2.8.9",
"dest-filename": "gson-2.8.9.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/google/code/gson/gson-parent/2.8.9/gson-parent-2.8.9.pom",
"sha512": "921e2ffed05e5dc8ec622d2546641f351f0189c275578b7cd7e5e291244545980c5c946cd90b87402bb0eb03ee4a7c0e2257a9d3af3fbd00cfa2c53ae2ae05aa",
"dest": "offline-repository/com/google/code/gson/gson-parent/2.8.9",
"dest-filename": "gson-parent-2.8.9.pom"
},
{
"type": "file",
"url": "https://dl.google.com/dl/android/maven2/androidx/lifecycle/lifecycle-common-jvm/2.9.3/lifecycle-common-jvm-2.9.3.jar",
"sha512": "20b6ce1a985e807206cd0d5b9170908d4c9fe8fe00b457c5495affd9e46d3f3435e535efe5a4a4295ba0567fd863f641739b05229daf5d19a5b872a789d0882f",
"dest": "offline-repository/androidx/lifecycle/lifecycle-common-jvm/2.9.3",
"dest-filename": "lifecycle-common-jvm-2.9.3.jar"
},
{
"type": "file",
"url": "https://dl.google.com/dl/android/maven2/androidx/savedstate/savedstate-desktop/1.3.3/savedstate-desktop-1.3.3.jar",
"sha512": "5e2cae112f0e845f8489b6c5ad8aad7f83fa92acde868f0756a275ae518c84452b9459b7aaba77210ec5dfcbbef35fd146b607203bb6f54b1450cd6ef109e7b1",
"dest": "offline-repository/androidx/savedstate/savedstate-desktop/1.3.3",
"dest-filename": "savedstate-desktop-1.3.3.jar"
},
{
"type": "file",
"url": "https://plugins.gradle.org/m2/com/squareup/kotlinpoet-jvm/2.1.0/kotlinpoet-jvm-2.1.0.jar",
"sha512": "c24412d93fa08fc9a065a1c659f96bbb301d5ea2bc17308d3790a8d0972a967698de2e397db452087a71b8f47122a3024f7625b61d23cd996cdcb934894df5fd",
"dest": "offline-repository/com/squareup/kotlinpoet-jvm/2.1.0",
"dest-filename": "kotlinpoet-jvm-2.1.0.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/github/ajalt/clikt/clikt-jvm/5.0.3/clikt-jvm-5.0.3.jar",
"sha512": "0ac2aacaa23d65976b879fb246ae146f174f3ba8a18496619c52cd47e210c3ea6ce7242a5e2cba4d5254ea758828745ff7faafeee59342818fdcd7849b83bc9c",
"dest": "offline-repository/com/github/ajalt/clikt/clikt-jvm/5.0.3",
"dest-filename": "clikt-jvm-5.0.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/github/skydoves/landscapist-coil3-desktop/2.9.5/landscapist-coil3-desktop-2.9.5.jar",
"sha512": "18f998466be06fe9799a19b807740db5d79621d0c88d70dfe5a02be106c0dc78e35bc1905605bfaca6e05387f5283af3f1096d63f2427be3d73e368495d07560",
"dest": "offline-repository/com/github/skydoves/landscapist-coil3-desktop/2.9.5",
"dest-filename": "landscapist-coil3-desktop-2.9.5.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/github/skydoves/landscapist-core-desktop/2.9.5/landscapist-core-desktop-2.9.5.jar",
"sha512": "b7366dcfbefbd8e4d4c7919abc336ee77f99dd95b65448faf1c41010ee7a63f0e6054cd81339fc8f259ed320943a463d37696d66e50b125008baeb22ed48027a",
"dest": "offline-repository/com/github/skydoves/landscapist-core-desktop/2.9.5",
"dest-filename": "landscapist-core-desktop-2.9.5.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/com/github/skydoves/landscapist-desktop/2.9.5/landscapist-desktop-2.9.5.jar",
"sha512": "226693f5eb5b0e0380ad85e8c14b15ea2e9c0432488d9681668333dd18ff833bd1bca7d34b209e8987c4e4cf5aabef860baf01121bcd52d08c49e3762c698c8b",
"dest": "offline-repository/com/github/skydoves/landscapist-desktop/2.9.5",
"dest-filename": "landscapist-desktop-2.9.5.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/io/coil-kt/coil3/coil-network-okhttp-jvm/3.3.0/coil-network-okhttp-jvm-3.3.0.jar",
"sha512": "1f3a8d83837dcdcb79b9a3ed9bbc59a1673b573b686097324b78cb458877ac18ed03b766e33599e1345b3bb9ff2ddce057e07f92af9c3cd2bbb46f3bf3bf73a4",
"dest": "offline-repository/io/coil-kt/coil3/coil-network-okhttp-jvm/3.3.0",
"dest-filename": "coil-network-okhttp-jvm-3.3.0.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/io/github/detekt/sarif4k/sarif4k-jvm/0.5.0/sarif4k-jvm-0.5.0.jar",
"sha512": "0cf5510071cb8864d1a7553276c5714caf47a97176cdb7690b6d80f215711f388f8ab4ac21b55cb5609b17aa71b1ea0ae5f5121650db5a1ee993059cccde3e7a",
"dest": "offline-repository/io/github/detekt/sarif4k/sarif4k-jvm/0.5.0",
"dest-filename": "sarif4k-jvm-0.5.0.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/io/github/oshai/kotlin-logging-jvm/5.1.0/kotlin-logging-jvm-5.1.0.jar",
"sha512": "1c8adc1cbe449e0fa9fe5b6113d0e7a09e772bc2f31a92f99149790f0617340ba6c5d552ce5ac34871dd62d758b7363a30630894fb9d413669b9e931091aa97d",
"dest": "offline-repository/io/github/oshai/kotlin-logging-jvm/5.1.0",
"dest-filename": "kotlin-logging-jvm-5.1.0.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/components/components-resources-desktop/1.10.3/components-resources-desktop-1.10.3.jar",
"sha512": "bc9bbf92638601da83d922fc7b8583eeafaf236d4d3dba07b2658f4706127a24021dc6c5908e009cfabad07b06ae7e87381d0b7c3445380c89ad4a5843401711",
"dest": "offline-repository/org/jetbrains/compose/components/components-resources-desktop/1.10.3",
"dest-filename": "components-resources-desktop-1.10.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/foundation/foundation-desktop/1.10.3/foundation-desktop-1.10.3.jar",
"sha512": "9617b16eb194a3988f05dc05e4defb6693e5dc3ad90bb4b80a6911e174ff9c46374fe2886c1418b2a3314b72c3f80585d11a46d3928606244ca18554e0092516",
"dest": "offline-repository/org/jetbrains/compose/foundation/foundation-desktop/1.10.3",
"dest-filename": "foundation-desktop-1.10.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/runtime/runtime-desktop/1.10.3/runtime-desktop-1.10.3.jar",
"sha512": "cec8fcf3ef05065a8ebc31311d6fc3b2029717d8942560ba2aeabe66e5bb08da4d440bc4ec72479d078a555cfc19eef3848cb730b344a46e3b29a9a1e4011a30",
"dest": "offline-repository/org/jetbrains/compose/runtime/runtime-desktop/1.10.3",
"dest-filename": "runtime-desktop-1.10.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/runtime/runtime-saveable-desktop/1.9.3/runtime-saveable-desktop-1.9.3.jar",
"sha512": "9bfa029d2cff9a1d5c0cf01a74ba6ae50da585be27af2f1a63c3b059f7b37ef85bd8dfa21775e87bb4e6dd8654ffd90c8077f826ada81489dd7e3af0ad8519fb",
"dest": "offline-repository/org/jetbrains/compose/runtime/runtime-saveable-desktop/1.9.3",
"dest-filename": "runtime-saveable-desktop-1.9.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/ui/ui-desktop/1.10.3/ui-desktop-1.10.3.jar",
"sha512": "4f85a8baffad0717b32f8bf40a35ff106e9ea699694d358dc8c8f310ba1f844ee77847e4676fdcdd5220bec11a13d0db96111ed002790a0164e64c8a2e03a0a8",
"dest": "offline-repository/org/jetbrains/compose/ui/ui-desktop/1.10.3",
"dest-filename": "ui-desktop-1.10.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/ui/ui-graphics-desktop/1.7.3/ui-graphics-desktop-1.7.3.jar",
"sha512": "45080768e04f16ba8e728858240c25f76a588c424335c5864b8bd3fc9dd60d7412ab6003f5522128cbd5b14bbb0b4949a9eced564ecc57105189477313448007",
"dest": "offline-repository/org/jetbrains/compose/ui/ui-graphics-desktop/1.7.3",
"dest-filename": "ui-graphics-desktop-1.7.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/compose/ui/ui-tooling-preview-desktop/1.10.3/ui-tooling-preview-desktop-1.10.3.jar",
"sha512": "f5f2804cd8893f0f1ec9cdd31a3125e303b4cbd6e3e860ff5318d1e342d5dc171397c0f2333647c3db14eddd49809087c1bd09501c7e238bdd69b72b42e5a35c",
"dest": "offline-repository/org/jetbrains/compose/ui/ui-tooling-preview-desktop/1.10.3",
"dest-filename": "ui-tooling-preview-desktop-1.10.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-core-jvm/1.7.3/kotlinx-serialization-core-jvm-1.7.3.jar",
"sha512": "7b89cfd2eb13f75a47a2e6fc08e1731adb4ddf1533192dba467c208f2f467a9461ac019ee616347ec7b5db371322881ebec6cfb3ae8023aca1146cc9eddbef71",
"dest": "offline-repository/org/jetbrains/kotlinx/kotlinx-serialization-core-jvm/1.7.3",
"dest-filename": "kotlinx-serialization-core-jvm-1.7.3.jar"
},
{
"type": "file",
"url": "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-serialization-json-io-jvm/1.9.0/kotlinx-serialization-json-io-jvm-1.9.0.jar",
"sha512": "e516a8f7418c2ab78b46f42294dad599704cf20e64184d8d3ba34373d27dc9ed48feb8f22f74f64cf69d3ef55f59056de9cedf4e8cf96979a2beb1ad23b96abf",
"dest": "offline-repository/org/jetbrains/kotlinx/kotlinx-serialization-json-io-jvm/1.9.0",
"dest-filename": "kotlinx-serialization-json-io-jvm-1.9.0.jar"
}
]
---
### Roadmap/E1 BACKEND HANDOFF (roadmap/E1_BACKEND_HANDOFF.md)
# E1 — backend handoff
Status: client-side complete on `feature/e1-external-imports` (PR #461). Two backend endpoints required before E1 reaches GA. One consolidation question with E6.
---
## What the client expects
### 1. `POST /v1/external-match` — required
Match a batch of installed-app fingerprints to GitHub repos. Anonymous (no `X-GitHub-Token`). Used by the wizard's match-resolution pipeline; today the client mocks this endpoint behind the `tweaks.externalMatchSearchEnabled` flag (default `false`).
**Request:**
```http
POST /v1/external-match
Content-Type: application/json
{
"platform": "android",
"candidates": [
{
"packageName": "com.example.foo",
"appLabel": "Foo App",
"signingFingerprint": "AB:CD:EF:...",
"installerKind": "browser",
"manifestHint": { "owner": null, "repo": null }
}
]
}
```
| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `platform` | string enum | yes | `android` for E1 |
| `candidates` | array | yes | 1..25 items per request (client batches) |
| `candidates[].packageName` | string | yes | `^[\w.-]{1,255}$` |
| `candidates[].appLabel` | string | yes | utf-8, 1..200 chars |
| `candidates[].signingFingerprint` | string\|null | optional | `^[0-9A-F]{2}(:[0-9A-F]{2}){31}$` SHA-256 hex |
| `candidates[].installerKind` | string enum\|null | optional | `obtainium`, `fdroid`, `play`, `aurora`, `galaxy`, `oem_other`, `browser`, `sideload`, `system`, `github_store_self`, `unknown` |
| `candidates[].manifestHint.owner` | string\|null | optional | `^[\w.-]{1,39}$` |
| `candidates[].manifestHint.repo` | string\|null | optional | `^[\w.-]{1,100}$` |
**`manifestHint` semantics.** The entire `candidates[].manifestHint` object MAY be omitted when the client found no in-APK hint; today's client always sends it as `{ "owner": null, "repo": null }` for symmetry, but backends should treat omission and a present-but-fully-null object identically (no hint provided). Validation runs on each non-null field independently — e.g., if `manifestHint.owner` is null and `manifestHint.repo` is non-null, only `manifestHint.repo` is regex-validated against `^[\w.-]{1,100}$`. A present `manifestHint` with both `owner` AND `repo` non-null is the only shape that should drive the manifest-hint scoring branch; partial values (one null, one not) should be treated as no hint and fall through to the search/fingerprint paths.
**Response (200):**
```json
{
"matches": [
{
"packageName": "com.example.foo",
"candidates": [
{
"owner": "octocat",
"repo": "hello-world",
"confidence": 0.78,
"source": "search",
"stars": 1240,
"description": "Example application"
}
]
}
]
}
```
`source` enum: `manifest` | `search` | `fingerprint`. `candidates[]` sorted by confidence descending, capped at 5. `stars` and `description` may be null.
**Other status codes:**
- `400` — invalid body
- `429` — rate limited; include `Retry-After` (in seconds). **Current client behavior:** `BackendApiClient.postExternalMatch` throws `RateLimitedException` on 429 and `ExternalImportRepositoryImpl.resolveMatches` logs the failure per-batch and continues with the remaining batches; no automatic WorkManager-backed retry is scheduled today. The plan called for WorkManager retry on `Retry-After` but it isn't wired yet — a backend that hard-rate-limits aggressively will see partial-result wizard sessions until that retry path is implemented in `resolveMatches`.
- `503` — partial outage. **Current client behavior:** `ExternalImportRepositoryImpl.resolveMatches` runs three strategies in parallel — manifest hints (parsed locally from each candidate's `AndroidManifest.xml`), signing-cert seed (looked up locally from the cached `signing_fingerprints` table), and the backend match call. When `BackendApiClient.postExternalMatch` fails with 503, only the backend strategy drops out for that batch; manifest-derived suggestions and signing-cert hits still flow through unaffected. So the client degrades to "local-only matching" — *not* manifest-only — as long as the seed sync has run at least once. Newly-installed apps with no manifest hint and no fingerprint match will see no suggestions until the backend recovers.
**Server-side scoring (per plan §3.2):**
- If `manifestHint.owner` and `repo` present → validate via HEAD against GitHub → `manifest` match at confidence 1.0
- If `signingFingerprint` present → look up in `signing_fingerprint → (owner, repo)` table → `fingerprint` match at confidence 0.92
- Else → score top 5 search results: exact-name match +0.4, substring +0.2, owner login matches packageName author segment +0.2, star bucket +0.05/0.10/0.15, has APK assets in last 5 releases +0.10 (else **−0.20** — heavy penalty for no-APK repos), description contains "Android"/"APK" +0.05
- Cap search-only confidence at 0.85 (keeps out of auto-link tier)
**Confidence clamping.** Backend MUST clamp every emitted `confidence` to `[0.0, 1.0]` before serialising the response. The −0.20 no-APK penalty plus other negative signals can produce a negative pre-clamp score for very weak matches; clamp those to 0.0 rather than emitting negative values. Rationale: client tier logic uses ≥0.85 (auto-link), 0.5..0.85 (preselected wizard suggestion), <0.5 (wizard with no preselect), and `RepoCandidateRow` displays `confidence * 100` percent rounded to int — client also runs a defensive `coerceIn(0, 100)` on the percentage but treating that as the source of truth on the wire would let invalid backend payloads slip through analytics. Manifest (1.0) and fingerprint (0.92) paths are already fixed values and don't require clamping; only the search-scoring path needs it.
**Cache:** 24h server-side keyed on `(packageName, appLabel, signingFingerprint)`. Including `signingFingerprint` in the key means a returning user with a different fingerprint (e.g., reinstalled the app from a different source after a key rotation) bypasses the cache and gets a fresh look-up. If `signingFingerprint` is null, treat the null itself as part of the key — don't merge null-fingerprint hits with the same package's known-fingerprint hits. (Original plan §3.2 wording was inverted — please use this clarified version.)
**Rate limit:** 60 req/hour/IP. Include `Retry-After` on 429.
**DTO:** `core/data/src/commonMain/kotlin/zed/rainxch/core/data/dto/ExternalMatchRequest.kt` and `ExternalMatchResponse.kt` already match this shape.
---
### 2. `GET /v1/signing-seeds` — required
Paginated incremental dump of signing-cert → GitHub-repo mappings, seeded from F-Droid index. Anonymous.
**Request:**
```http
GET /v1/signing-seeds?since=1714521600000&platform=android&cursor=opaque-cursor-string
```
| Param | Type | Required | Notes |
| --- | --- | --- | --- |
| `since` | integer (epoch millis) | optional | Only return rows observed at or after this timestamp |
| `cursor` | string | optional | Opaque pagination token from prior response |
| `platform` | string enum | required | `android` for E1 |
**Response (200):**
```json
{
"rows": [
{
"fingerprint": "AB:CD:EF:...",
"owner": "octocat",
"repo": "hello-world",
"observedAt": 1714521600000
}
],
"nextCursor": "opaque-string-or-null"
}
```
**Important:** `observedAt` MUST be **epoch milliseconds** (not seconds). The client stores this and passes it as `since` on the next sync. Mixing units silently corrupts the incremental cursor — there's a unit-tagged comment on the client DTO calling this out.
**Page size:** 1000 rows recommended. Initial seed: 5–15k rows total (5–15 page calls). Daily delta: typically <200 rows.
**Source:** F-Droid index has the `(certificate, source-code-URL)` mapping for ~5k OSS apps. Backend extracts it into the seed table on a daily cron.
**DTO:** `core/data/src/commonMain/kotlin/zed/rainxch/core/data/dto/SigningFingerprintSeedResponse.kt`
---
### 3. Flag flip (no client release needed)
After both endpoints are in production, flip `tweaks.externalMatchSearchEnabled` to `true`. The client picks this up via the existing tweaks DataStore channel — no client release required.
If your tweaks infrastructure doesn't yet support remote-driven values for that flag, ship the default-on flip in the next client release.
---
## Optional (defer if needed)
- **Fingerprint-derived match in `POST /v1/external-match`** — frontend computes this locally from the seed table, so the backend's `source: "fingerprint"` path is a redundant safety net. Skip if it's complex.
- **Dynamic seed updates with full diff** — initial seed is enough for v1. Daily delta can land later.
---
## Cannot defer
- **`POST /v1/external-match`** — without it, Strategy 2 (search) is mocked and the medium-confidence tier produces no matches. Manifest hints + signing-cert seed still work, so the wizard is usable but coverage is narrower.
---
## Telemetry overlap with E6 (clarification needed)
E6's handoff document (`feature/e6-telemetry`) §3.4 "Import (E1 / E2)" says to wire `IMPORT_SCAN_STARTED`, `IMPORT_SCAN_COMPLETED`, `IMPORT_MATCH_ATTEMPTED`, `IMPORT_AUTO_LINKED`, `IMPORT_MANUALLY_LINKED`, `IMPORT_SKIPPED` from `LibraryImportViewModel.kt` via the new `ProductTelemetry` interface.
**Two issues:**
1. The class is named `ExternalImportViewModel.kt`, not `LibraryImportViewModel.kt`. Heads-up so the next person doesn't grep for the wrong name.
2. **E1 already fires those six events** via the existing `TelemetryRepository.import*` methods. The wiring is in:
- `ExternalImportRepositoryImpl.runFullScan / runDeltaScan` (importScanStarted / importScanCompleted / importMatchAttempted / importAutoLinked)
- `ExternalImportViewModel.skipPackage / pickSuggestion / submitSearchOverride` (importSkipped / importManuallyLinked / importSearchOverrideUsed / importSearchOverrideNoResults / importPermissionRequested / importPermissionOutcome)
- `DetailsViewModel.confirmUnlinkExternalApp` (importUnlinkedFromDetails)
**Decision needed before E6 wires §3.4:** does `ProductTelemetry` replace `TelemetryRepository` for these events, or do they coexist? If "replace," E6's port is the right approach and the existing `TelemetryRepository.import*` calls get deleted. If "coexist," every import action fires *two* events on the wire — almost certainly wrong.
Please respond with which path you intend so the E6 work doesn't double-emit.
---
## Endpoint URLs
The client base URL is the existing `BACKEND_BASE_URL`. Both new endpoints are siblings of `events`, `categories`, `topics`, `repo`, `releases`, `readme`, `user`. No new auth/scope needed.
## Verification path
```sh
# 1. Build the client APK against staging
./gradlew :composeApp:assembleDebug
# 2. Flip the flag locally for testing
adb shell am start-foreground-service \
-a zed.rainxch.tweak.SET \
--es key external_match_search_enabled --ez value true
# 3. Open the wizard, observe match calls hit your endpoint
adb logcat -s OkHttp | grep external-match
# 4. Confirm match results render with `source: "search"` chip in the wizard UI
```
---
### .Claude/Settings.Local.Json (.claude/settings.local.json)
{
"permissions": {
"allow": [
"Bash(grep -r \"\\\\.FLATPAK\\\\|Flatpak\\\\|flatpak\" . --include=*.kt)",
"Bash(./gradlew *)",
"Bash(rtk find *)",
"WebSearch",
"WebFetch(domain:github.com)",
"WebFetch(domain:www.jetbrains.com)",
"WebFetch(domain:youtrack.jetbrains.com)",
"WebFetch(domain:raw.githubusercontent.com)",
"WebFetch(domain:blog.jetbrains.com)",
"Bash(rtk grep *)",
"Bash(git checkout *)",
"Bash(rtk proxy *)",
"Bash(git pull *)",
"Bash(git cherry-pick *)",
"Bash(gh pr create --base main --head chore/drop-legacy-query-hash --title 'Stop sending hashed search queries to legacy /v1/events' --body ' *)",
"Bash(gh pr create --base main --head fix/auth-stuck-on-direct-and-dialog-loop --title 'Fix sign-in getting stuck with DNS error + dialog re-firing over auth screen' --body ' *)"
]
}
}
---
### .Github/FUNDING.Yml (.github/FUNDING.yml)
# These are supported funding model platforms
github: [rainxchzed]
---
### .Github/ISSUE TEMPLATE/Bug Report (.github/ISSUE_TEMPLATE/bug_report.md)
---
name: Bug report
about: Something's broken? Tell us what's happening.
title: ''
labels: bug
assignees: ''
---
> Already in the app? **Profile → Send feedback** auto-fills app version, platform, and installer. Fastest path.
## What's wrong
What were you trying to do, and what happened instead?
## How to reproduce
1.
2.
3.
## Your setup
App version · Android version + device, **or** Desktop OS + version.
## Anything else
Screenshots, logs, the GitHub repo URL you were trying to install — whatever helps. Don't sweat it if you don't have all of it.
---
### .Github/ISSUE TEMPLATE/Feature Request (.github/ISSUE_TEMPLATE/feature_request.md)
---
name: Feature request
about: Pitch an idea — start with the user pain.
title: ''
labels: enhancement
assignees: ''
---
## The pain
What are you trying to do, and where does the current app fall short?
## What would help
What would the app do differently if this were solved?
## Anything else
Mockups, links, alternatives you considered. Optional.
---
### .Github/Workflows/Build Desktop Platforms.Yml (.github/workflows/build-desktop-platforms.yml)
name: Build Desktop Platform Installers
on:
push:
branches:
- generate-installers
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
JAVA_VERSION: '21'
JAVA_DISTRIBUTION: 'temurin'
GRADLE_OPTS: >-
-Dorg.gradle.daemon=false
-Dorg.gradle.parallel=true
-Dorg.gradle.caching=true
-Dorg.gradle.vfs.watch=false
jobs:
build-windows:
runs-on: windows-latest
outputs:
windows-artifact-id: ${{ steps.upload-windows.outputs.artifact-id }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
gradle-home-cache-cleanup: true
- name: Grant execute permission for gradlew
run: chmod +x gradlew
shell: bash
- name: Build Windows installers (EXE & MSI)
run: |
set -euo pipefail
retry() {
local n=1 max=3 delay=5
while true; do
echo "Attempt #$n: $*"
"$@" && break
[ $n -ge $max ] && { echo "Failed after $n attempts."; return 1; }
n=$((n+1)); echo "Retrying in ${delay}s..."; sleep $delay; delay=$((delay*2))
done
}
retry ./gradlew :composeApp:packageExe :composeApp:packageMsi :composeApp:createDistributable
shell: bash
# Flatten .exe + .msi into a single directory so the uploaded artifact
# zip contains them at the root (no `exe/` and `msi/` subdirectories).
# SignPath's artifact-configuration XML uses simple `*.exe` / `*.msi`
# globs at zip root; nested paths cause "Expected path to match exactly
# 1 item, but found 0" because upload-artifact@v4 strips the longest
# common prefix only, so multi-source paths preserve their tail dirs.
- name: Stage Windows installers for upload
run: |
set -euo pipefail
mkdir -p windows-staging
cp composeApp/build/compose/binaries/main/exe/*.exe windows-staging/
cp composeApp/build/compose/binaries/main/msi/*.msi windows-staging/
ls -la windows-staging/
shell: bash
- name: Upload Windows installers
id: upload-windows
uses: actions/upload-artifact@v4
with:
name: windows-installers
path: windows-staging/*
if-no-files-found: error
retention-days: 30
compression-level: 6
# Portable build: zip the jpackage app-image (launcher + bundled JRE) so
# users can unzip and run GitHub-Store.exe with no installer (#700). The
# launcher is unsigned — it ships as its own artifact and never passes
# through the SignPath job, which signs only the .exe/.msi installers.
- name: Stage Windows portable (zip app-image)
shell: pwsh
run: |
$line = (Select-String -Path 'gradle/libs.versions.toml' -Pattern 'projectVersionName' | Select-Object -First 1).Line
$version = [regex]::Match($line, '"(.*?)"').Groups[1].Value
if ([string]::IsNullOrWhiteSpace($version)) { Write-Error "Could not read projectVersionName"; exit 1 }
$appDir = "composeApp/build/compose/binaries/main/app/Komi-Store"
if (-not (Test-Path $appDir)) { $appDir = "composeApp/build/compose/binaries/main/app-image/Komi-Store" }
if (-not (Test-Path $appDir)) { Write-Error "app-image directory not found"; exit 1 }
New-Item -ItemType Directory -Force -Path windows-portable | Out-Null
$zip = "windows-portable/Komi-Store-$version-windows-portable.zip"
Compress-Archive -Path $appDir -DestinationPath $zip -Force
Get-Item $zip | Format-List
- name: Upload Windows portable
uses: actions/upload-artifact@v4
with:
name: windows-portable
path: windows-portable/*
if-no-files-found: error
retention-days: 30
compression-level: 0
sign-windows:
name: Sign Windows installers (SignPath)
needs: build-windows
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
actions: write
steps:
# Fail loudly if any SignPath config is missing instead of letting the
# action surface a generic auth/lookup error halfway through the run.
# Policy slug lives in a repo variable so swapping test-signing →
# release-signing once SignPath issues the prod cert is a one-click
# change in repo Settings, with no code edit needed.
- name: Verify SignPath configuration
env:
ORG_ID: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
POLICY_SLUG: ${{ vars.SIGNPATH_SIGNING_POLICY_SLUG }}
run: |
set -euo pipefail
missing=()
[ -n "${ORG_ID:-}" ] || missing+=("SIGNPATH_ORGANIZATION_ID (secret)")
[ -n "${API_TOKEN:-}" ] || missing+=("SIGNPATH_API_TOKEN (secret)")
[ -n "${POLICY_SLUG:-}" ] || missing+=("SIGNPATH_SIGNING_POLICY_SLUG (variable)")
if [ ${#missing[@]} -gt 0 ]; then
echo "::error::Missing SignPath configuration:"
printf '::error:: - %s\n' "${missing[@]}"
exit 1
fi
echo "Signing policy: ${POLICY_SLUG}"
shell: bash
# Pinned to the v2 release commit instead of @v2 so a force-push to the
# mutable tag (or a compromise of the SignPath org) cannot inject code
# into a job that holds id-token: write and the SignPath API token.
# When bumping, look up the new SHA via:
# gh api repos/signpath/github-action-submit-signing-request/git/refs/tags/
- name: Submit signing request
uses: signpath/github-action-submit-signing-request@b9d91eadd323de506c0c81cf0c7fe7438f3360fd # v2 (2025-10-23)
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
project-slug: 'GitHub-Store'
signing-policy-slug: ${{ vars.SIGNPATH_SIGNING_POLICY_SLUG }}
artifact-configuration-slug: 'initial'
github-artifact-id: ${{ needs.build-windows.outputs.windows-artifact-id }}
wait-for-completion: true
output-artifact-directory: signed-artifacts
- name: Upload signed Windows installers
uses: actions/upload-artifact@v4
with:
name: windows-installers-signed
path: signed-artifacts/*
if-no-files-found: error
retention-days: 30
compression-level: 0
# Remove the unsigned upload so only the SignPath-signed installers are
# downloadable from the run page and end up in the draft release.
# Without this, both windows-installers (unsigned) and
# windows-installers-signed coexist as 30-day artifacts.
- name: Delete unsigned Windows artifact
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARTIFACT_ID: ${{ needs.build-windows.outputs.windows-artifact-id }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
gh api -X DELETE "repos/${REPO}/actions/artifacts/${ARTIFACT_ID}"
echo "Deleted unsigned artifact id=${ARTIFACT_ID}"
shell: bash
build-macos:
strategy:
matrix:
include:
- os: macos-15-intel
arch: x64
- os: macos-latest
arch: arm64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
gradle-home-cache-cleanup: true
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build macOS installers (DMG & PKG)
run: |
set -euo pipefail
retry() {
local n=1 max=3 delay=5
while true; do
echo "Attempt #$n: $*"
"$@" && break
[ $n -ge $max ] && { echo "Failed after $n attempts."; return 1; }
n=$((n+1)); echo "Retrying in ${delay}s..."; sleep $delay; delay=$((delay*2))
done
}
retry ./gradlew :composeApp:packageDmg :composeApp:packagePkg
shell: bash
- name: Upload macOS installers
uses: actions/upload-artifact@v4
with:
name: macos-installers-${{ matrix.arch }}
path: |
composeApp/build/compose/binaries/main/dmg/*.dmg
composeApp/build/compose/binaries/main/pkg/*.pkg
if-no-files-found: error
retention-days: 30
compression-level: 6
build-linux:
strategy:
matrix:
include:
- os: ubuntu-latest
label: modern
gradle-tasks: >-
:composeApp:packageDeb
:composeApp:packageRpm
:composeApp:packageAppImage
- os: ubuntu-22.04
label: debian12-compat
gradle-tasks: >-
:composeApp:packageDeb
:composeApp:packageRpm
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
gradle-home-cache-cleanup: true
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build Linux installers
run: |
set -euo pipefail
retry() {
local n=1 max=3 delay=5
while true; do
echo "Attempt #$n: $*"
"$@" && break
[ $n -ge $max ] && { echo "Failed after $n attempts."; return 1; }
n=$((n+1)); echo "Retrying in ${delay}s..."; sleep $delay; delay=$((delay*2))
done
}
retry ./gradlew ${{ matrix.gradle-tasks }}
shell: bash
- name: List AppImage build output
if: matrix.label == 'modern'
run: |
echo "=== Listing build output ==="
find composeApp/build/compose/binaries/main -maxdepth 3 -type d 2>/dev/null || echo "Directory not found"
echo "=== All files ==="
find composeApp/build/compose/binaries/main -maxdepth 4 -type f 2>/dev/null | head -30 || echo "No files found"
shell: bash
- name: Build AppImage with appimagetool
if: matrix.label == 'modern'
run: |
set -euo pipefail
# Find the directory containing the app launcher (bin/Komi-Store)
APP_ROOT=""
for candidate in \
composeApp/build/compose/binaries/main/app-image/Komi-Store \
composeApp/build/compose/binaries/main/app/Komi-Store \
composeApp/build/compose/binaries/main/app-image \
composeApp/build/compose/binaries/main/app; do
if [ -f "$candidate/bin/Komi-Store" ]; then
APP_ROOT="$candidate"
echo "Found app root at: $candidate"
break
fi
done
if [ -z "$APP_ROOT" ]; then
echo "ERROR: Could not find app launcher (bin/Komi-Store)"
find composeApp/build/compose/binaries/main -type f -name "Komi-Store" 2>/dev/null || true
exit 1
fi
# Download appimagetool
wget -q https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
# Create AppDir from Compose output
APPDIR="Komi-Store.AppDir"
mv "$APP_ROOT" "$APPDIR"
# Install the JVM-direct launcher that bypasses the jpackage native
# launcher (crashes in glibc setenv() on glibc >= 2.42, see GH#563).
cp packaging/linux/github-store-launcher.sh "$APPDIR/bin/github-store-launcher.sh"
chmod +x "$APPDIR/bin/github-store-launcher.sh"
# Compose strips native commands from the bundled runtime (no bin/java).
# The AppRun -> launcher wrapper execs "lib/runtime/bin/java", so restore
# that launcher from the build JDK; the runtime bundles libjli.so / libjvm.so,
# resolved via $ORIGIN/../lib (GH#746). This AppDir is also the source for the
# Arch package below, so both pick up the fix.
if [ ! -x "$APPDIR/lib/runtime/bin/java" ]; then
mkdir -p "$APPDIR/lib/runtime/bin"
cp "$JAVA_HOME/bin/java" "$APPDIR/lib/runtime/bin/java"
chmod +x "$APPDIR/lib/runtime/bin/java"
fi
# Create AppRun entry point
cat > "$APPDIR/AppRun" << 'EOF'
#!/bin/bash
SELF=$(readlink -f "$0")
HERE=${SELF%/*}
exec "${HERE}/bin/github-store-launcher.sh" "$@"
EOF
chmod +x "$APPDIR/AppRun"
# Create .desktop file
cat > "$APPDIR/github-store.desktop" << 'EOF'
[Desktop Entry]
Type=Application
Name=Komi Store
Exec=komi-store
Icon=github-store
Categories=Development;
Comment=Cross-platform app store for GitHub releases
EOF
# Copy icon to AppDir root (required by appimagetool)
cp "$APPDIR/lib/Komi-Store.png" "$APPDIR/github-store.png"
# Build .AppImage
OUTPUT="composeApp/build/compose/binaries/main/Komi-Store-x86_64.AppImage"
UPINFO="gh-releases-zsync|rainxchzed|Github-Store|latest|*x86_64.AppImage.zsync"
ARCH=x86_64 APPIMAGE_EXTRACT_AND_RUN=1 ./appimagetool-x86_64.AppImage -u "$UPINFO" "$APPDIR" "$OUTPUT"
# appimagetool may place .zsync in the working directory; move it next to the AppImage
ZSYNC_NAME="$(basename "$OUTPUT").zsync"
if [ -f "$ZSYNC_NAME" ] && [ ! -f "$OUTPUT.zsync" ]; then
mv "$ZSYNC_NAME" "$OUTPUT.zsync"
fi
echo "Created AppImage and zsync:"
ls -lh "$OUTPUT" "$OUTPUT.zsync"
shell: bash
- name: Patch deb (headless compat + t64 deps GH#124 + native-launcher bypass GH#563)
run: |
set -euo pipefail
WRAPPER="$(pwd)/packaging/linux/github-store-launcher.sh"
for deb in composeApp/build/compose/binaries/main/deb/*.deb; do
[ -f "$deb" ] || continue
echo "Patching: $deb"
tmpdir=$(mktemp -d)
dpkg-deb -R "$deb" "$tmpdir"
for script in "$tmpdir/DEBIAN/postinst" "$tmpdir/DEBIAN/prerm" "$tmpdir/DEBIAN/postrm"; do
[ -f "$script" ] || continue
# Make xdg-desktop-menu / xdg-icon-resource / xdg-mime calls non-fatal
# so install/remove succeeds in headless environments (WSL, containers, servers)
sed -i '/xdg-desktop-menu\|xdg-icon-resource\|xdg-mime/{/|| true$/!s/$/ || true/}' "$script"
done
# GH#124: glibc time64 ("t64") library rename. jpackage/dpkg-shlibdeps
# emits host-derived deps: t64 names on Ubuntu 24.04+/Debian 13, bare
# names on Ubuntu 22.04/Debian 12. Neither single name installs on both.
# Rewrite to alternative-dependency form so one .deb covers every distro.
control="$tmpdir/DEBIAN/control"
if [ -f "$control" ]; then
if grep -q 'libasound2t64' "$control"; then
sed -i 's/\blibasound2t64\b/libasound2 | libasound2t64/g' "$control"
elif grep -q 'libasound2' "$control"; then
sed -i 's/\blibasound2\b/libasound2 | libasound2t64/g' "$control"
fi
if grep -q 'libpng16-16t64' "$control"; then
sed -i 's/\blibpng16-16t64\b/libpng16-16 | libpng16-16t64/g' "$control"
elif grep -q 'libpng16-16' "$control"; then
sed -i 's/\blibpng16-16\b/libpng16-16 | libpng16-16t64/g' "$control"
fi
echo "Depends after t64 rewrite:"; grep -i '^Depends' "$control" || true
fi
# Replace the jpackage native launcher with the JVM-direct wrapper.
# The native launcher crashes in glibc setenv() on glibc >= 2.42
# before the JVM maps (GH#563). The installed .desktop Exec path is
# unchanged, so it transparently runs the wrapper instead.
launcher="$(find "$tmpdir/opt" -type f -path '*/bin/Komi-Store' 2>/dev/null | head -n1 || true)"
if [ -n "$launcher" ] && head -c4 "$launcher" | grep -q $'\x7fELF'; then
echo "Swapping native launcher: $launcher"
mv "$launcher" "${launcher}.bin"
cp "$WRAPPER" "$launcher"
chmod +x "$launcher"
else
echo "WARNING: native launcher not found or already a script in $deb"
fi
# Compose strips native commands from the bundled runtime, so it ships no
# bin/java. The wrapper above execs "$ROOTDIR/lib/runtime/bin/java"; restore
# that launcher from the build JDK (libjli.so / libjvm.so are bundled and
# resolve via $ORIGIN/../lib, GH#746).
runtime="$(find "$tmpdir/opt" -maxdepth 4 -type d -name runtime | head -n1 || true)"
if [ -n "$runtime" ] && [ ! -x "$runtime/bin/java" ]; then
mkdir -p "$runtime/bin"
cp "$JAVA_HOME/bin/java" "$runtime/bin/java"
chmod 0755 "$runtime/bin/java"
echo "Restored bundled java launcher at $runtime/bin/java"
fi
dpkg-deb -b "$tmpdir" "$deb"
rm -rf "$tmpdir"
echo "Patched successfully: $deb"
done
shell: bash
- name: Patch rpm (native-launcher bypass GH#563)
run: |
set -uo pipefail
shopt -s nullglob
rpms=(composeApp/build/compose/binaries/main/rpm/*.rpm)
[ ${#rpms[@]} -gt 0 ] || { echo "No rpm to patch"; exit 0; }
if ! sudo apt-get install -y rpmrebuild rpm >/dev/null 2>&1; then
echo "::warning::could not install rpmrebuild; dropping unpatched rpm(s) to avoid shipping the GH#563 crash"
rm -f "${rpms[@]}"
exit 0
fi
WRAPPER="$(pwd)/packaging/linux/github-store-launcher.sh"
OUTDIR="$(mktemp -d)"
for rpm in "${rpms[@]}"; do
echo "Patching: $rpm"
# Overwrite the native launcher in-place with the JVM-direct wrapper, and
# restore bin/java (Compose strips native commands from the runtime, GH#746).
# rpmrebuild repopulates %files from the buildroot, so the new file ships.
if rpmrebuild --change-files="cp '$WRAPPER' ./opt/komi-store/bin/Komi-Store; chmod 0755 ./opt/komi-store/bin/Komi-Store; mkdir -p ./opt/komi-store/lib/runtime/bin; cp '$JAVA_HOME/bin/java' ./opt/komi-store/lib/runtime/bin/java; chmod 0755 ./opt/komi-store/lib/runtime/bin/java" \
-p -n -d "$OUTDIR" "$rpm"; then
rebuilt="$(find "$OUTDIR" -name '*.rpm' -newer "$WRAPPER" | head -n1 || true)"
if [ -n "$rebuilt" ]; then
mv -f "$rebuilt" "$rpm"
echo "Patched successfully: $rpm"
else
echo "::warning::rpmrebuild produced no output for $rpm; dropping it to avoid shipping the GH#563 crash"
rm -f "$rpm"
fi
else
echo "::warning::rpmrebuild failed for $rpm; dropping it to avoid shipping the GH#563 crash"
rm -f "$rpm"
fi
rm -f "$OUTDIR"/*/*.rpm 2>/dev/null || true
done
rm -rf "$OUTDIR"
shell: bash
- name: Upload Linux installers
uses: actions/upload-artifact@v4
with:
name: linux-installers-${{ matrix.label }}
path: |
composeApp/build/compose/binaries/main/deb/*.deb
composeApp/build/compose/binaries/main/rpm/*.rpm
if-no-files-found: error
retention-days: 30
compression-level: 6
- name: Upload Linux AppImage
if: matrix.label == 'modern'
uses: actions/upload-artifact@v4
with:
name: linux-appimage
path: |
composeApp/build/compose/binaries/main/Komi-Store-x86_64.AppImage
composeApp/build/compose/binaries/main/Komi-Store-x86_64.AppImage.zsync
if-no-files-found: error
retention-days: 30
compression-level: 0
- name: Build Arch Linux package (.pkg.tar.zst)
if: matrix.label == 'modern'
run: |
set -euo pipefail
VERSION=$(grep 'projectVersionName' gradle/libs.versions.toml | head -1 | sed 's/.*= *"\(.*\)"/\1/')
PKG_NAME="komi-store"
PKG_DIR="pkg-root"
# Find the app directory produced by packageAppImage
APP_ROOT=""
for candidate in \
composeApp/build/compose/binaries/main/app/Komi-Store \
composeApp/build/compose/binaries/main/app-image/Komi-Store; do
if [ -f "$candidate/bin/Komi-Store" ]; then
APP_ROOT="$candidate"
break
fi
done
# Fall back to the AppDir we created earlier if still present
if [ -z "$APP_ROOT" ] && [ -f "Komi-Store.AppDir/bin/Komi-Store" ]; then
APP_ROOT="Komi-Store.AppDir"
fi
if [ -z "$APP_ROOT" ]; then
echo "ERROR: Could not find app directory for Arch packaging"
exit 1
fi
# Build the package tree
mkdir -p "$PKG_DIR/opt/komi-store"
cp -a "$APP_ROOT"/. "$PKG_DIR/opt/komi-store/"
# Install the JVM-direct launcher that bypasses the jpackage native
# launcher (crashes in glibc setenv() on glibc >= 2.42, see GH#563).
cp packaging/linux/github-store-launcher.sh "$PKG_DIR/opt/komi-store/bin/github-store-launcher.sh"
chmod +x "$PKG_DIR/opt/komi-store/bin/github-store-launcher.sh"
# Launcher symlink
mkdir -p "$PKG_DIR/usr/bin"
ln -s "/opt/komi-store/bin/github-store-launcher.sh" "$PKG_DIR/usr/bin/komi-store"
# Desktop entry
mkdir -p "$PKG_DIR/usr/share/applications"
cat > "$PKG_DIR/usr/share/applications/komi-store.desktop" << 'EOF'
[Desktop Entry]
Type=Application
Name=Komi Store
Exec=komi-store
Icon=komi-store
Categories=Development;
Comment=Cross-platform app store for GitHub releases
StartupWMClass=komi-store
EOF
sed -i 's/^ //' "$PKG_DIR/usr/share/applications/komi-store.desktop"
# Icon
if [ -f "$PKG_DIR/opt/komi-store/lib/Komi-Store.png" ]; then
mkdir -p "$PKG_DIR/usr/share/icons/hicolor/256x256/apps"
cp "$PKG_DIR/opt/komi-store/lib/Komi-Store.png" \
"$PKG_DIR/usr/share/icons/hicolor/256x256/apps/komi-store.png"
fi
# .PKGINFO (pacman metadata — must be a flat file at archive root)
INSTALLED_SIZE=$(du -sb "$PKG_DIR" | cut -f1)
cat > "$PKG_DIR/.PKGINFO" << EOF
pkgname = ${PKG_NAME}
pkgver = ${VERSION}-1
pkgdesc = Cross-platform app store for GitHub releases
url = https://github.com/kurikomi-labs/komi-store
builddate = $(date +%s)
packager = GitHub Actions
arch = x86_64
license = GPL-3.0
size = ${INSTALLED_SIZE}
replaces = github-store
conflicts = github-store
depend = java-runtime>=21
depend = hicolor-icon-theme
EOF
sed -i 's/^ //' "$PKG_DIR/.PKGINFO"
# Create .pkg.tar.zst
sudo apt-get install -y zstd
OUTPUT_DIR="composeApp/build/compose/binaries/main/arch"
mkdir -p "$OUTPUT_DIR"
ARCHIVE="${PKG_NAME}-${VERSION}-1-x86_64.pkg.tar.zst"
cd "$PKG_DIR"
# .PKGINFO must come first in the archive
tar --zstd -cf "../${OUTPUT_DIR}/${ARCHIVE}" .PKGINFO opt usr
cd ..
echo "Created Arch package:"
ls -lh "${OUTPUT_DIR}/${ARCHIVE}"
shell: bash
- name: Upload Arch Linux package
if: matrix.label == 'modern'
uses: actions/upload-artifact@v4
with:
name: linux-arch
path: composeApp/build/compose/binaries/main/arch/*.pkg.tar.zst
if-no-files-found: error
retention-days: 30
compression-level: 0
release:
name: Draft release with all installers
needs: [sign-windows, build-macos, build-linux]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Read project version
id: version
run: |
set -euo pipefail
VERSION=$(grep 'projectVersionName' gradle/libs.versions.toml | head -1 | sed 's/.*= *"\(.*\)"/\1/')
if [ -z "$VERSION" ]; then
echo "ERROR: could not read projectVersionName from gradle/libs.versions.toml"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved release tag: v$VERSION"
shell: bash
- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Stage release files (rename arch / compat collisions)
run: |
set -euo pipefail
mkdir -p release-files
# Snapshot of what download-artifact@v4 actually produced —
# useful when build-output paths drift in the future.
# upload-artifact@v4 strips the longest common prefix, so paths
# like main/exe/*.exe + main/msi/*.msi land as exe/*.exe and
# msi/*.msi inside the artifact. Fixed shallow globs miss them;
# we use `find` below for resilience.
echo "=== Downloaded artifact tree ==="
find artifacts -maxdepth 4 -type f 2>/dev/null | sort
echo
# stage() returns 0 on a successful copy, 1 if the source is missing.
# Callers use the exit status to increment per-group counters so the
# completeness guard at the end can detect missing groups.
stage() {
local src="$1"
local target_name="$2"
if [ -f "$src" ]; then
cp "$src" "release-files/$target_name"
echo "Staged: $target_name"
return 0
fi
return 1
}
windows_count=0
windows_portable_count=0
macos_x64_count=0
macos_arm64_count=0
linux_modern_count=0
linux_debian12_count=0
linux_appimage_count=0
linux_arch_count=0
# Windows — names already unique (.exe, .msi). Files come from the
# signed artifact, not the raw build output, so they carry the
# SignPath Authenticode signature.
while IFS= read -r f; do
[ -n "$f" ] || continue
stage "$f" "$(basename "$f")" && windows_count=$((windows_count + 1)) || true
done < <(find artifacts/windows-installers-signed -type f \( -name '*.exe' -o -name '*.msi' \) 2>/dev/null)
# Windows portable — app-image zip from build-windows (unsigned, not
# routed through SignPath). Filename already carries version + arch.
while IFS= read -r f; do
[ -n "$f" ] || continue
stage "$f" "$(basename "$f")" && windows_portable_count=$((windows_portable_count + 1)) || true
done < <(find artifacts/windows-portable -type f -name '*.zip' 2>/dev/null)
# macOS — disambiguate x64 vs arm64 (Compose outputs identical filenames per arch)
while IFS= read -r f; do
[ -n "$f" ] || continue
base="$(basename "$f")"
ext="${base##*.}"
stem="${base%.*}"
stage "$f" "${stem}-x64.${ext}" && macos_x64_count=$((macos_x64_count + 1)) || true
done < <(find artifacts/macos-installers-x64 -type f \( -name '*.dmg' -o -name '*.pkg' \) 2>/dev/null)
while IFS= read -r f; do
[ -n "$f" ] || continue
base="$(basename "$f")"
ext="${base##*.}"
stem="${base%.*}"
stage "$f" "${stem}-arm64.${ext}" && macos_arm64_count=$((macos_arm64_count + 1)) || true
done < <(find artifacts/macos-installers-arm64 -type f \( -name '*.dmg' -o -name '*.pkg' \) 2>/dev/null)
# Linux modern — default Debian/RPM (unprefixed)
while IFS= read -r f; do
[ -n "$f" ] || continue
stage "$f" "$(basename "$f")" && linux_modern_count=$((linux_modern_count + 1)) || true
done < <(find artifacts/linux-installers-modern -type f \( -name '*.deb' -o -name '*.rpm' \) 2>/dev/null)
# Linux debian12-compat — suffix to avoid collision with modern
while IFS= read -r f; do
[ -n "$f" ] || continue
base="$(basename "$f")"
ext="${base##*.}"
stem="${base%.*}"
stage "$f" "${stem}-debian12.${ext}" && linux_debian12_count=$((linux_debian12_count + 1)) || true
done < <(find artifacts/linux-installers-debian12-compat -type f \( -name '*.deb' -o -name '*.rpm' \) 2>/dev/null)
# Linux AppImage + zsync (filenames already include -x86_64)
while IFS= read -r f; do
[ -n "$f" ] || continue
stage "$f" "$(basename "$f")" && linux_appimage_count=$((linux_appimage_count + 1)) || true
done < <(find artifacts/linux-appimage -type f \( -name '*.AppImage' -o -name '*.AppImage.zsync' \) 2>/dev/null)
# Linux Arch (.pkg.tar.zst already has version + arch in filename)
while IFS= read -r f; do
[ -n "$f" ] || continue
stage "$f" "$(basename "$f")" && linux_arch_count=$((linux_arch_count + 1)) || true
done < <(find artifacts/linux-arch -type f -name '*.pkg.tar.zst' 2>/dev/null)
echo
echo "Final staged files:"
ls -la release-files/
echo
echo "Per-group counts: windows=$windows_count windows-portable=$windows_portable_count macos-x64=$macos_x64_count macos-arm64=$macos_arm64_count linux-modern=$linux_modern_count linux-debian12=$linux_debian12_count linux-appimage=$linux_appimage_count linux-arch=$linux_arch_count"
# Completeness guard: refuse to ship an incomplete release. Each
# group must produce >= 1 staged file. Without this guard, a build
# regression (e.g. AppImage step silently producing nothing) would
# ship a draft release missing the affected group and we'd discover
# it only when users complained.
missing=()
[ "$windows_count" -eq 0 ] && missing+=("Windows installers (.exe/.msi)")
[ "$windows_portable_count" -eq 0 ] && missing+=("Windows portable (.zip)")
[ "$macos_x64_count" -eq 0 ] && missing+=("macOS x64 (.dmg/.pkg)")
[ "$macos_arm64_count" -eq 0 ] && missing+=("macOS arm64 (.dmg/.pkg)")
[ "$linux_modern_count" -eq 0 ] && missing+=("Linux modern (.deb/.rpm)")
[ "$linux_debian12_count" -eq 0 ] && missing+=("Linux debian12-compat (.deb/.rpm)")
[ "$linux_appimage_count" -eq 0 ] && missing+=("Linux AppImage (.AppImage/.zsync)")
[ "$linux_arch_count" -eq 0 ] && missing+=("Linux Arch (.pkg.tar.zst)")
if [ ${#missing[@]} -gt 0 ]; then
echo
echo "ERROR: missing artifacts for the following groups:"
printf " - %s\n" "${missing[@]}"
echo
echo "Refusing to publish an incomplete release."
exit 1
fi
shell: bash
- name: Create or update draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
if gh release view "$TAG" >/dev/null 2>&1; then
# Release with this tag exists. Only clobber assets if it's still
# a DRAFT — we never silently overwrite assets on a published
# release. Operator must bump projectVersionName in
# gradle/libs.versions.toml to roll a new tag.
is_draft=$(gh release view "$TAG" --json isDraft -q '.isDraft')
if [ "$is_draft" = "true" ]; then
echo "Draft release $TAG already exists — replacing assets via --clobber..."
gh release upload "$TAG" release-files/* --clobber
else
echo "ERROR: release $TAG is already PUBLISHED."
echo "Refusing to clobber published assets."
echo
echo "If you intended to ship a new version, bump"
echo "projectVersionName in gradle/libs.versions.toml first,"
echo "then re-push to generate-installers."
exit 1
fi
else
echo "Creating new draft release $TAG..."
gh release create "$TAG" \
--draft \
--title "$VERSION" \
--generate-notes \
release-files/*
fi
shell: bash
---
### .Github/Workflows/Homebrew Tap Publish.Yml (.github/workflows/homebrew-tap-publish.yml)
name: Publish to Homebrew Tap
on:
release:
types: [released]
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g. v1.8.3)'
required: true
jobs:
update-cask:
name: Update Homebrew Cask
runs-on: ubuntu-latest
steps:
- name: Resolve release tag
id: tag
env:
INPUT_TAG: ${{ github.event.inputs.tag }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
if [ -n "$INPUT_TAG" ]; then
TAG="$INPUT_TAG"
else
TAG="$RELEASE_TAG"
fi
if [ -z "$TAG" ]; then
echo "No tag resolved from event inputs" >&2
exit 1
fi
VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved tag=$TAG version=$VERSION"
- name: Download macOS DMGs
env:
REPO: ${{ github.repository }}
TAG: ${{ steps.tag.outputs.tag }}
VERSION: ${{ steps.tag.outputs.version }}
run: |
set -euo pipefail
BASE="https://github.com/${REPO}/releases/download/${TAG}"
curl -fSL -o arm64.dmg "${BASE}/Komi-Store-${VERSION}-arm64.dmg"
curl -fSL -o x64.dmg "${BASE}/Komi-Store-${VERSION}-x64.dmg"
ls -la *.dmg
- name: Compute SHA256
id: hash
run: |
set -euo pipefail
SHA_ARM=$(sha256sum arm64.dmg | awk '{print $1}')
SHA_X64=$(sha256sum x64.dmg | awk '{print $1}')
echo "arm=$SHA_ARM" >> "$GITHUB_OUTPUT"
echo "intel=$SHA_X64" >> "$GITHUB_OUTPUT"
echo "arm64=$SHA_ARM"
echo "x64=$SHA_X64"
- name: Checkout tap repo
uses: actions/checkout@v4
with:
repository: kurikomi-labs/homebrew-komi-store
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: homebrew-tap
- name: Patch cask
working-directory: homebrew-tap
env:
NEW_VERSION: ${{ steps.tag.outputs.version }}
NEW_SHA_ARM: ${{ steps.hash.outputs.arm }}
NEW_SHA_INTEL: ${{ steps.hash.outputs.intel }}
run: |
python3 - <<'EOF'
import os, re, sys
path = "Casks/komi-store.rb"
version = os.environ["NEW_VERSION"]
sha_arm = os.environ["NEW_SHA_ARM"]
sha_intel = os.environ["NEW_SHA_INTEL"]
text = open(path).read()
new_text, n_v = re.subn(r'version\s+"[^"]+"', f'version "{version}"', text, count=1)
if n_v != 1:
print("Failed to patch version stanza", file=sys.stderr)
sys.exit(1)
pattern = re.compile(
r'sha256 arm:\s+"[0-9a-f]+",\s*\n\s*intel:\s+"[0-9a-f]+"'
)
replacement = (
f'sha256 arm: "{sha_arm}",\n'
f' intel: "{sha_intel}"'
)
new_text, n_s = pattern.subn(replacement, new_text, count=1)
if n_s != 1:
print("Failed to patch sha256 stanza", file=sys.stderr)
sys.exit(1)
open(path, "w").write(new_text)
print("Patched cask:")
print(new_text)
EOF
- name: Commit + push
working-directory: homebrew-tap
env:
VERSION: ${{ steps.tag.outputs.version }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Casks/komi-store.rb
if git diff --cached --quiet; then
echo "Cask already up to date"
exit 0
fi
git commit -m "Bump komi-store to ${VERSION}"
git push
---
### .Github/Workflows/Scoop Publish.Yml (.github/workflows/scoop-publish.yml)
name: Publish to Scoop
on:
release:
types: [released]
workflow_dispatch:
jobs:
trigger-bucket:
name: Trigger Scoop bucket update
runs-on: ubuntu-latest
steps:
- name: Dispatch Excavator
env:
GH_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
run: |
gh api --method POST \
repos/kurikomi-labs/komi-store-scoop-bucket/dispatches \
-f event_type=komi-store-release
---
### .Github/Workflows/Winget Publish.Yml (.github/workflows/winget-publish.yml)
name: Publish to WinGet
on:
release:
types: [released]
jobs:
publish-msi:
name: Publish MSI to WinGet
runs-on: ubuntu-latest
steps:
- uses: vedantmgoyal9/winget-releaser@main
with:
identifier: zed.rainxch.githubstore
installers-regex: '\.msi$'
token: ${{ secrets.WINGET_TOKEN }}
---