Что такое репозиторий
Clink читает паки из публичных репозиториев GitHub. Вы добавляете репозиторий по имени, Clink читает его последний релиз, и каждый файл проверяется до установки. Ничего не выгружается, и ничего вашего не выполняется на сервере.
Укажите owner/repository, github.com/owner/repository или полный HTTPS-URL. Clink проверяет каждый манифест релиза и каждый файл, прежде что-либо можно будет загрузить.
Выберите вид
У каждого вида паков своё расширение файла и своё название коллекции внутри манифеста, и к каждому Clink применяет свой предел размера. Выберите строку, которую публикуете, и держитесь её: тема, положенная в панели, просто не будет прочитана.
| Вид | Файл | Коллекция | Наибольший файл, в байтах | Официальный репозиторий |
|---|---|---|---|---|
| Темы | .clinktheme | themes | 128 000 | anti-ltd/clink-themes |
| Раскладки | .clinklayout | layouts | 512 000 | anti-ltd/clink-layouts |
| Профили | .clinkprofile | profiles | 256 000 | anti-ltd/clink-profiles |
| Звуки | .clinkpack | sounds | 512 000 | anti-ltd/clink-sounds |
| Шрифты | .otf .ttf | fonts | 32 000 000 | anti-ltd/clink-fonts |
| Панели | .clinkpanel | panels | 50 000 | anti-ltd/clink-panels |
| Действия | .clinkext | actions | 48 000 | anti-ltd/clink-actions |
| Плагины | .clinkplugin | plugins | 66 000 | anti-ltd/clink-plugins |
Языковые паки составляют исключение. Там пак представляет собой набор файлов словаря и моделей, а не один документ, и официальный репозиторий несёт в себе инструменты, которые их собирают. Начинайте с его README, а не с этой страницы.
Начните с официального репозитория
Самый быстрый путь начать с форка. Он приходит с папкой паков, сборщиком манифеста и рабочим процессом публикации, уже связанными между собой, плюс рабочие примеры, которые можно скопировать.
# Everything a repository needs is already wired together in the official one.
gh repo fork anti-ltd/clink-panels --clone
cd clink-panels
# Your packs replace the examples. Keep tools/ and .github/.
rm Panels/*.clinkpanel
cp ~/Downloads/my-panel.clinkpanel Panels/kaomoji-plus.clinkpanelСохраните tools/ и .github/workflows/. Именно они превращают push в релиз, который Clink умеет читать; форк без них не публикует ничего.
Или соберите его из трёх файлов
В репозитории нет ничего особенного. Ему нужны папка с паками, скрипт, который пишет манифест, и рабочий процесс, который выпускает релиз.
my-panels/
├── Panels/
│ └── kaomoji.clinkpanel # one file per pack, the name is the id
├── tools/
│ └── build-manifest.py # writes manifest.json from that folder
└── .github/workflows/
└── release.yml # turns a push into a releaseРабочий процесс делает три вещи: пересобирает манифест, удаляет предыдущий релиз и публикует новый с меткой latest, приложив файлы паков и манифест. Это всё.
name: Release panels
on:
push:
branches: [main]
paths: ["Panels/**", "tools/**", ".github/workflows/release.yml"]
permissions: { contents: write }
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python3 tools/build-manifest.py
- run: gh release delete latest --yes || true
env: { GH_TOKEN: "${{ github.token }}" }
- run: gh release create latest Panels/*.clinkpanel manifest.json --title "Latest panels" --latest
env: { GH_TOKEN: "${{ github.token }}" }Сборщик обходит папку и пишет по записи на файл. Это единственное место, откуда берутся хеш и размер в байтах, поэтому он и запускается в рабочем процессе, а не вручную.
#!/usr/bin/env python3
import hashlib, json, os, pathlib
root = pathlib.Path(__file__).resolve().parents[1]
repository = os.environ.get("GITHUB_REPOSITORY", "<owner>/<repository>")
packs = []
for path in sorted((root / "Panels").glob("*.clinkpanel")):
data = path.read_bytes()
pack = json.loads(data)
packs.append({
"id": path.stem,
"name": pack["name"],
"version": "latest",
"asset": {
"path": path.name,
"url": f"https://github.com/{repository}/releases/download/latest/{path.name}",
"sha256": hashlib.sha256(data).hexdigest(),
"byteCount": len(data),
},
})
(root / "manifest.json").write_text(json.dumps({"version": "latest", "panels": packs}, indent=2))Манифест
Каждый релиз публикует manifest.json рядом с файлами паков, и Clink читает его из последнего релиза по адресу https://github.com/<owner>/<repository>/releases/latest/download/manifest.json. В каждой записи указаны файл, его адрес внутри того же релиза, его хеш SHA-256 и точный размер в байтах.
{
"version": "latest",
"panels": [
{
"id": "kaomoji",
"name": "Kaomoji",
"version": "latest",
"asset": {
"path": "kaomoji.clinkpanel",
"url": "https://github.com/<owner>/<repository>/releases/download/latest/kaomoji.clinkpanel",
"sha256": "8f14e45fce…",
"byteCount": 2048
}
}
]
}Название коллекции должно совпадать с видом. Панели идут под panels, темы под themes, и так далее по всей таблице выше.
Проверьте до публикации
Пак в репозитории остаётся тем же самым файлом, который можно открыть вручную, так что сперва проверьте коротким путём: отправьте его на телефон через AirDrop или положите в «Файлы» и откройте в Clink. Затем сверьте манифест, который пишет ваш скрипт.
python3 tools/build-manifest.py
cat manifest.json- Запустите сборщик. Он перепишет manifest.json по тому, что лежит в папке прямо сейчас.
- Прочитайте написанное. В каждой записи должен быть файл, который действительно существует, и совпадающий с ним размер в байтах.
- Откройте сам файл пака в Clink и поработайте с ним. Панель или действие попадут в свой редактор, где их можно запустить.
Публикация
git add Panels manifest.json
git commit -m "Add my first panel"
git pushОтправьте коммит в main, дальше всё сделает рабочий процесс. Он заменяет релиз latest, а не дополняет его, поэтому последний push это всегда то, что получают остальные.
Откройте эту вкладку после того, как репозиторий опубликует релиз.
Добавьте его в Clink
- Откройте «Общие», затем «Репозитории», и добавьте владелец/репозиторий.
- Откройте вкладку своего вида и потяните вниз для обновления. Ваши паки появятся под теми именами, которые дал им манифест.
- Нажмите на любой, чтобы скачать. Clink проверит его и установит, как любой другой пак.
Для пакетов с данными достаточно добавить репозиторий: темы, раскладки, профили, звуки, шрифты и языки. Панели, действия и плагины несут логику, поэтому каждому репозиторию нужен собственный переключатель, прежде чем Clink установит любой из них, и приложение спрашивает в первый раз.
Панели содержат ограниченную интерактивную логику. Разрешайте только репозитории, которым доверяете.
Что проверяет Clink
- Адрес использует HTTPS на github.com и ведёт в релизы того репозитория, который вы добавили.
- Размер загрузки в точности совпадает с манифестом, а её хеш SHA-256 из 64 символов сходится.
- У файла правильное расширение, и он разбирается как тот тип пака, за который себя выдаёт.
- Панели, действия и плагины проходят политику исходного кода перед сохранением.
Если загрузка отклонена, причина будет одной из этих пяти. Сообщение в приложении намеренно короткое, поэтому проверяйте их по порядку.
| Проверка | Отклоняется, если |
|---|---|
github.com | Адрес не HTTPS на github.com и не ведёт в релизы добавленного вами репозитория. Манифест не может указывать куда-то ещё, даже на другой ваш репозиторий. |
byteCount | Размер файла не совпадает с заявленным в манифесте или превышает предел для своего вида. Пересборка манифеста после каждой правки решает почти все такие случаи. |
sha256 | Хеш не сходится с байтами. Обычно манифест записали до последнего изменения файла. |
path | Имя файла не оканчивается расширением, которого требует вид, или пытается выбраться из релиза двумя точками. |
source | Панель, действие или плагин не прошли политику исходного кода: слишком длинные или содержат фрагмент, который политика отвергает. |
Обновление и отзыв
Идентификатором служит имя файла без расширения, и именно он делает публикацию обновлением. Сохраните имя, и новый релиз заменит копию, которая у людей уже есть. Переименуйте файл, и вы опубликовали второй пак рядом с первым.
Удаление пака из репозитория прекращает новые загрузки. До телефонов, где он уже стоит, это не доходит, поэтому неудачный релиз стоит заменять, а не удалять.
Официальные репозитории
Сделайте форк любого из них, чтобы начать. Каждый собирает собственный манифест и публикует себя через GitHub Actions.