Compare commits
4 Commits
7e0e7e4c29
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 62c9b8e59d | |||
| a4591655b7 | |||
| 5a7542fb4c | |||
| 9989d81b51 |
3
.gitignore
vendored
@@ -27,3 +27,6 @@ android/captures/
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
/archive
|
/archive
|
||||||
|
|
||||||
|
# claude code
|
||||||
|
.claude/
|
||||||
|
|||||||
245
README.md
@@ -1,20 +1,17 @@
|
|||||||
# synq, a tiny android-to-org capture system.
|
# synq, a tiny android-to-org capture system.
|
||||||
|
synq consists of an Android app for capturing notes items and a docker agent that pulls notes and saves them to a local .org file.
|
||||||
|
|
||||||
open app.
|
1. Open Synq app
|
||||||
type, optionally mark as todo, optionally add tags, save.
|
2. Type note, mark as TODO (opt), add tags (opt), save.
|
||||||
if home server accessible, post unsynced captures to lan-only service and appended to `synq.org`.
|
3. If home server accessible, post unsynced captures to lan-only service and appended to `synq.org`.
|
||||||
|
|
||||||
## non-goals
|
<p>
|
||||||
- no org parser on android
|
<img src="docs/home-v1.png" alt="home-screen-v1" width="220">
|
||||||
- no agenda on android
|
<img src="docs/history-v1.png" alt="history-screen-v1" width="220">
|
||||||
- no sync provider dependency
|
<img src="docs/settings-v1.png" alt="settings-v1" width="220">
|
||||||
- no nextcloud file editing
|
</p>
|
||||||
- no conflict resolution
|
|
||||||
- no public internet exposure
|
|
||||||
- no ai tagging in v1
|
|
||||||
- no account system in v1
|
|
||||||
|
|
||||||
## architecture
|
## Architecture
|
||||||
|
|
||||||
```text
|
```text
|
||||||
android app
|
android app
|
||||||
@@ -28,219 +25,43 @@ home server
|
|||||||
python + fastapi
|
python + fastapi
|
||||||
sqlite idempotency store
|
sqlite idempotency store
|
||||||
append-only org writer
|
append-only org writer
|
||||||
|
|
||||||
flow
|
|
||||||
user saves capture locally
|
|
||||||
app marks it pending
|
|
||||||
sync runs when server is reachable
|
|
||||||
app posts pending captures to fastapi
|
|
||||||
server validates, dedupes by id, appends to phone.org
|
|
||||||
app marks capture synced
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## v1 behavior
|
1. user saves capture locally
|
||||||
|
2. app marks it pending
|
||||||
|
3. sync runs when server is reachable
|
||||||
|
4. app posts pending captures to fastapi
|
||||||
|
5. server validates, dedupes by id, appends to phone.org
|
||||||
|
6. app marks capture synced
|
||||||
|
|
||||||
the app launches into a focused text box. the user can type immediately.
|
|
||||||
|
|
||||||
controls:
|
## Build & Deploy
|
||||||
|
First, clone the repo.
|
||||||
|
|
||||||
- note/todo toggle
|
Build and deploy `synq-server`, the docker container that listens for new notes and writes to the local file.
|
||||||
- optional tags field
|
|
||||||
- save
|
|
||||||
- save and close
|
|
||||||
- sync now
|
|
||||||
- small history view showing pending, synced, and failed entries
|
|
||||||
|
|
||||||
each capture has:
|
Then, build and install the `synq` app.
|
||||||
|
|
||||||
- stable client-generated id
|
Finally, retrieve the token (`token.txt` in the docker container's data directory, or from the container logs `docker logs synq-server`)
|
||||||
- created timestamp with timezone
|
|
||||||
- kind: `note` or `todo`
|
|
||||||
- body text
|
|
||||||
- tags
|
|
||||||
- device name
|
|
||||||
- sync status
|
|
||||||
- optional last error
|
|
||||||
|
|
||||||
## org output
|
### 1. synq-server (docker)
|
||||||
|
- Build from `docker build -t synq-server ./server`
|
||||||
todo:
|
- Run (replace paths and token as needed):
|
||||||
|
```docker
|
||||||
```org
|
|
||||||
* TODO buy printer paper :home:errands:
|
|
||||||
:PROPERTIES:
|
|
||||||
:CREATED: [2026-05-17 sun 14:31]
|
|
||||||
:SOURCE: android
|
|
||||||
:ID: phone-20260517-143122-a8f2
|
|
||||||
:END:
|
|
||||||
```
|
|
||||||
|
|
||||||
note:
|
|
||||||
|
|
||||||
```org
|
|
||||||
* note :retcon:
|
|
||||||
:PROPERTIES:
|
|
||||||
:CREATED: [2026-05-17 sun 14:33]
|
|
||||||
:SOURCE: android
|
|
||||||
:ID: phone-20260517-143322-b91c
|
|
||||||
:END:
|
|
||||||
|
|
||||||
mobile capture should stay dumb and append-only.
|
|
||||||
```
|
|
||||||
|
|
||||||
## server paths
|
|
||||||
|
|
||||||
default container paths:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/data/synq.org
|
|
||||||
/data/capture.sqlite3
|
|
||||||
/data/rejected.log
|
|
||||||
```
|
|
||||||
|
|
||||||
recommended unraid host mapping:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/mnt/user/synq/phone-capture:/data
|
|
||||||
```
|
|
||||||
|
|
||||||
or map `/data/synq.org` directly to wherever the real org file lives. prefer a dedicated capture file first; emacs can include it in agenda later.
|
|
||||||
|
|
||||||
## security model
|
|
||||||
|
|
||||||
v1 is lan-only. bind the service to the host lan and do not expose it through swag/cloudflare/public dns.
|
|
||||||
|
|
||||||
minimum useful controls:
|
|
||||||
|
|
||||||
- shared bearer token in app and server env
|
|
||||||
- server only accepts json
|
|
||||||
- server rejects empty body
|
|
||||||
- server dedupes ids
|
|
||||||
- server writes append-only org
|
|
||||||
- server never edits or parses existing org
|
|
||||||
- docker volume is backed up
|
|
||||||
|
|
||||||
## repo layout
|
|
||||||
|
|
||||||
suggested monorepo:
|
|
||||||
|
|
||||||
```text
|
|
||||||
synq/
|
|
||||||
android/
|
|
||||||
app/
|
|
||||||
server/
|
|
||||||
app/
|
|
||||||
main.py
|
|
||||||
models.py
|
|
||||||
org_writer.py
|
|
||||||
store.py
|
|
||||||
tests/
|
|
||||||
Dockerfile
|
|
||||||
pyproject.toml
|
|
||||||
docs/
|
|
||||||
api.md
|
|
||||||
android-notes.md
|
|
||||||
server-notes.md
|
|
||||||
docker-compose.example.yml
|
|
||||||
.env.example
|
|
||||||
tasks.org
|
|
||||||
README.md
|
|
||||||
```
|
|
||||||
|
|
||||||
## build order
|
|
||||||
|
|
||||||
1. implement server first using curl tests.
|
|
||||||
2. implement android local capture with room.
|
|
||||||
3. implement manual sync.
|
|
||||||
4. add workmanager opportunistic sync.
|
|
||||||
5. add history screen and resend handling.
|
|
||||||
6. polish launch speed and widget/share-target only after core path works.
|
|
||||||
|
|
||||||
## build & deploy
|
|
||||||
|
|
||||||
### server (docker)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# build
|
|
||||||
docker build -t synq-server ./server
|
|
||||||
|
|
||||||
# run (replace paths and token as needed)
|
|
||||||
docker run -d --name synq --restart=unless-stopped \
|
docker run -d --name synq --restart=unless-stopped \
|
||||||
-p 8765:8765 \
|
-p 8765:8765 \
|
||||||
-v /mnt/user/synq/data:/data \
|
-v /mnt/user/synq/data:/data \
|
||||||
synq-server
|
synq-server
|
||||||
```
|
```
|
||||||
|
|
||||||
the server generates a random token on first start and logs it prominently. copy it into the android app settings. to use a fixed token instead, pass `-e PHONE_CAPTURE_TOKEN=yourtoken`.
|
The server generates a random token on first start and logs it prominently. Copy it into the android app settings. To use a fixed token instead, pass `-e PHONE_CAPTURE_TOKEN=yourtoken`.
|
||||||
|
|
||||||
to rebuild after a `git pull`:
|
### 2. synq (android)
|
||||||
|
Download apk from Releases, on the right
|
||||||
```bash
|
|
||||||
git pull
|
|
||||||
docker build -t synq-server ./server
|
|
||||||
docker stop synq && docker rm synq
|
|
||||||
# re-run the docker run command above
|
|
||||||
```
|
|
||||||
|
|
||||||
### android
|
|
||||||
|
|
||||||
open `android/` in Android Studio and hit **Sync**. then either:
|
|
||||||
|
|
||||||
|
Or, build from source:
|
||||||
|
Open `android/` in Android Studio and hit **Sync**. then either:
|
||||||
- **run on device/emulator directly** from Android Studio (▶), or
|
- **run on device/emulator directly** from Android Studio (▶), or
|
||||||
- **build a release APK** from the terminal:
|
- **build a release APK**
|
||||||
|
Then sideload to a connected device:
|
||||||
```bash
|
- terminal: `adb install app/build/outputs/apk/release/app-release-unsigned.apk`
|
||||||
cd android
|
|
||||||
./gradlew assembleRelease
|
|
||||||
# output: app/build/outputs/apk/release/app-release-unsigned.apk
|
|
||||||
```
|
|
||||||
|
|
||||||
sideload to a connected device:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
adb install app/build/outputs/apk/release/app-release-unsigned.apk
|
|
||||||
```
|
|
||||||
|
|
||||||
### releasing on gitea
|
|
||||||
|
|
||||||
tag the commit and push the tag:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git tag v1.0.0
|
|
||||||
git push gitea v1.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
then go to **Releases → New Release** in the Gitea UI, pick the tag, and drag the APK into the assets box. anyone on the LAN can download it from there.
|
|
||||||
|
|
||||||
## backup
|
|
||||||
|
|
||||||
### what to back up
|
|
||||||
|
|
||||||
the server writes to one directory (the `/data` volume). back up the whole thing:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/data/synq.org ← the canonical org capture file
|
|
||||||
/data/capture.sqlite3 ← idempotency store (dedup ids)
|
|
||||||
/data/token.txt ← auto-generated token (if not using PHONE_CAPTURE_TOKEN env var)
|
|
||||||
```
|
|
||||||
|
|
||||||
on unraid the host path is whatever you mapped in compose, e.g. `/mnt/user/ben/synq/phone-capture`.
|
|
||||||
|
|
||||||
### restore behavior
|
|
||||||
|
|
||||||
- restore the `/data` volume to a new container and start it. the server will pick up where it left off.
|
|
||||||
- `synq.org` is append-only plain text — it is human-readable and recoverable even without the sqlite db.
|
|
||||||
- if `capture.sqlite3` is lost but `synq.org` is intact, the server will accept re-posted captures that were already in the org file (no dedup). the android app marks them synced either way (`already_seen` or `accepted`), so the only side effect is duplicate org entries for anything re-synced. restore the db from backup to avoid this.
|
|
||||||
- if `token.txt` is lost, delete it and let the server generate a new one on next start, then update the app settings.
|
|
||||||
|
|
||||||
## v2 parking lot
|
|
||||||
|
|
||||||
- android share target
|
|
||||||
- quick settings tile or widget
|
|
||||||
- tag chips from recent tags
|
|
||||||
- configurable default tag
|
|
||||||
- edit unsynced entries only
|
|
||||||
- multi-device capture
|
|
||||||
- wireguard-aware sync
|
|
||||||
- local export/import
|
|
||||||
- optional emacs ingest helpers
|
|
||||||
|
|||||||
@@ -14,13 +14,17 @@ android {
|
|||||||
applicationId = "me.hgsky.synq"
|
applicationId = "me.hgsky.synq"
|
||||||
minSdk = 31
|
minSdk = 31
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 1
|
versionCode = 2
|
||||||
versionName = "0.1.0"
|
versionName = "1.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Keep Room entities and DAOs
|
||||||
|
-keep class me.hgsky.synq.data.db.** { *; }
|
||||||
|
|
||||||
|
# Keep Retrofit/OkHttp
|
||||||
|
-dontwarn okhttp3.**
|
||||||
|
-keep class okhttp3.** { *; }
|
||||||
|
|
||||||
|
# Keep kotlinx.serialization
|
||||||
|
-keepattributes *Annotation*, InnerClasses
|
||||||
|
-dontnote kotlinx.serialization.AnnotationsKt
|
||||||
|
-keepclassmembers class kotlinx.serialization.json.** { *** Companion; }
|
||||||
|
-keepclasseswithmembers class **$$serializer { *; }
|
||||||
|
-keepclassmembers @kotlinx.serialization.Serializable class ** {
|
||||||
|
*** Companion;
|
||||||
|
*** serializer(...);
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
@@ -1,8 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<!--
|
||||||
|
~ Copyright (C) 2026 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="512"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="512">
|
||||||
<path android:fillColor="#22569d" android:pathData="M0,0h108v108h-108z"/>
|
<path
|
||||||
|
android:pathData="M0,0.96h512v512h-512z"
|
||||||
|
android:strokeWidth="1.00157"
|
||||||
|
android:fillColor="#22569d"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -18,11 +18,15 @@
|
|||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="512"
|
android:viewportWidth="512"
|
||||||
android:viewportHeight="512">
|
android:viewportHeight="512">
|
||||||
<path
|
<path
|
||||||
|
android:pathData="M0,0.96h512v512h-512z"
|
||||||
|
android:strokeWidth="1.00157"
|
||||||
|
android:fillColor="#22569d"/>
|
||||||
|
<path
|
||||||
android:pathData="m189.14,130.52h133.72c7.25,0 13.08,5.83 13.08,13.08v220.93c0,7.25 -5.83,13.08 -13.08,13.08H189.14c-7.25,0 -13.08,-5.83 -13.08,-13.08V143.6c0,-7.25 5.83,-13.08 13.08,-13.08z"
|
android:pathData="m189.14,130.52h133.72c7.25,0 13.08,5.83 13.08,13.08v220.93c0,7.25 -5.83,13.08 -13.08,13.08H189.14c-7.25,0 -13.08,-5.83 -13.08,-13.08V143.6c0,-7.25 5.83,-13.08 13.08,-13.08z"
|
||||||
android:strokeWidth="2.90698"
|
android:strokeWidth="2.90698"
|
||||||
android:fillColor="#ffffff"
|
android:fillColor="#ffffff"
|
||||||
android:strokeColor="#000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FF000000"
|
android:fillColor="#FF000000"
|
||||||
android:pathData="m222.27,361.68h66.86c1.61,0 2.91,1.3 2.91,2.91 0,1.61 -1.3,2.91 -2.91,2.91h-66.86c-1.61,0 -2.91,-1.3 -2.91,-2.91 0,-1.61 1.3,-2.91 2.91,-2.91z"
|
android:pathData="m222.27,361.68h66.86c1.61,0 2.91,1.3 2.91,2.91 0,1.61 -1.3,2.91 -2.91,2.91h-66.86c-1.61,0 -2.91,-1.3 -2.91,-2.91 0,-1.61 1.3,-2.91 2.91,-2.91z"
|
||||||
@@ -32,7 +36,7 @@
|
|||||||
android:pathData="M193.63,145.03H318.63c1.61,0 2.91,1.3 2.91,2.91v197.67c0,1.61 -1.3,2.91 -2.91,2.91H193.63c-1.61,0 -2.91,-1.3 -2.91,-2.91V147.94c0,-1.61 1.3,-2.91 2.91,-2.91z"
|
android:pathData="M193.63,145.03H318.63c1.61,0 2.91,1.3 2.91,2.91v197.67c0,1.61 -1.3,2.91 -2.91,2.91H193.63c-1.61,0 -2.91,-1.3 -2.91,-2.91V147.94c0,-1.61 1.3,-2.91 2.91,-2.91z"
|
||||||
android:strokeWidth="2.90698"
|
android:strokeWidth="2.90698"
|
||||||
android:fillColor="#22569d"
|
android:fillColor="#22569d"
|
||||||
android:strokeColor="#000000"/>
|
android:strokeColor="#00000000"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="m210.25,196.07h-11.2v-42.2h11.2v3.18h-7.43v35.84h7.43zM241.81,186.76h-5.11l-7.22,-11.99 -7.24,11.99h-5.04l9.88,-15.17 -9.08,-14.51h4.79l6.79,11.17 6.84,-11.17h4.66l-9.11,14.33zM260.1,196.07h-11.2v-3.18h7.38v-35.84h-7.38v-3.18h11.2zM280.54,179.61q0.77,0 1.45,0.3 0.7,0.3 1.2,0.82 0.52,0.52 0.82,1.23 0.3,0.68 0.3,1.48 0,0.77 -0.3,1.45 -0.3,0.68 -0.82,1.2 -0.5,0.5 -1.2,0.79 -0.68,0.3 -1.45,0.3 -0.79,0 -1.48,-0.3 -0.68,-0.3 -1.2,-0.79 -0.5,-0.52 -0.79,-1.2 -0.3,-0.68 -0.3,-1.45 0,-0.79 0.3,-1.48 0.3,-0.7 0.79,-1.23 0.52,-0.52 1.2,-0.82 0.68,-0.3 1.48,-0.3zM306.11,179.61q0.77,0 1.45,0.3 0.7,0.3 1.2,0.82 0.52,0.52 0.82,1.23 0.3,0.68 0.3,1.48 0,0.77 -0.3,1.45 -0.3,0.68 -0.82,1.2 -0.5,0.5 -1.2,0.79 -0.68,0.3 -1.45,0.3 -0.79,0 -1.48,-0.3 -0.68,-0.3 -1.2,-0.79 -0.5,-0.52 -0.79,-1.2 -0.3,-0.68 -0.3,-1.45 0,-0.79 0.3,-1.48 0.3,-0.7 0.79,-1.23 0.52,-0.52 1.2,-0.82 0.68,-0.3 1.48,-0.3z"
|
android:pathData="m210.25,196.07h-11.2v-42.2h11.2v3.18h-7.43v35.84h7.43zM241.81,186.76h-5.11l-7.22,-11.99 -7.24,11.99h-5.04l9.88,-15.17 -9.08,-14.51h4.79l6.79,11.17 6.84,-11.17h4.66l-9.11,14.33zM260.1,196.07h-11.2v-3.18h7.38v-35.84h-7.38v-3.18h11.2zM280.54,179.61q0.77,0 1.45,0.3 0.7,0.3 1.2,0.82 0.52,0.52 0.82,1.23 0.3,0.68 0.3,1.48 0,0.77 -0.3,1.45 -0.3,0.68 -0.82,1.2 -0.5,0.5 -1.2,0.79 -0.68,0.3 -1.45,0.3 -0.79,0 -1.48,-0.3 -0.68,-0.3 -1.2,-0.79 -0.5,-0.52 -0.79,-1.2 -0.3,-0.68 -0.3,-1.45 0,-0.79 0.3,-1.48 0.3,-0.7 0.79,-1.23 0.52,-0.52 1.2,-0.82 0.68,-0.3 1.48,-0.3zM306.11,179.61q0.77,0 1.45,0.3 0.7,0.3 1.2,0.82 0.52,0.52 0.82,1.23 0.3,0.68 0.3,1.48 0,0.77 -0.3,1.45 -0.3,0.68 -0.82,1.2 -0.5,0.5 -1.2,0.79 -0.68,0.3 -1.45,0.3 -0.79,0 -1.48,-0.3 -0.68,-0.3 -1.2,-0.79 -0.5,-0.52 -0.79,-1.2 -0.3,-0.68 -0.3,-1.45 0,-0.79 0.3,-1.48 0.3,-0.7 0.79,-1.23 0.52,-0.52 1.2,-0.82 0.68,-0.3 1.48,-0.3z"
|
||||||
android:strokeWidth="0.726744"
|
android:strokeWidth="0.726744"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
Normal file
|
After Width: | Height: | Size: 1004 B |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 872 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
Normal file
|
After Width: | Height: | Size: 652 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.5 KiB |
BIN
docs/history-v1.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
docs/home-v1.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
docs/settings-v1.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
150
docs/spec.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Specifications
|
||||||
|
|
||||||
|
## v1 behavior
|
||||||
|
|
||||||
|
the app launches into a focused text box. the user can type immediately.
|
||||||
|
|
||||||
|
controls:
|
||||||
|
|
||||||
|
- note/todo toggle
|
||||||
|
- optional tags field
|
||||||
|
- save
|
||||||
|
- save and close
|
||||||
|
- sync now
|
||||||
|
- small history view showing pending, synced, and failed entries
|
||||||
|
|
||||||
|
each capture has:
|
||||||
|
|
||||||
|
- stable client-generated id
|
||||||
|
- created timestamp with timezone
|
||||||
|
- kind: `note` or `todo`
|
||||||
|
- body text
|
||||||
|
- tags
|
||||||
|
- device name
|
||||||
|
- sync status
|
||||||
|
- optional last error
|
||||||
|
|
||||||
|
## org output
|
||||||
|
|
||||||
|
todo:
|
||||||
|
|
||||||
|
```org
|
||||||
|
* TODO buy printer paper :home:errands:
|
||||||
|
:PROPERTIES:
|
||||||
|
:CREATED: [2026-05-17 sun 14:31]
|
||||||
|
:SOURCE: android
|
||||||
|
:ID: phone-20260517-143122-a8f2
|
||||||
|
:END:
|
||||||
|
```
|
||||||
|
|
||||||
|
note:
|
||||||
|
|
||||||
|
```org
|
||||||
|
* note :retcon:
|
||||||
|
:PROPERTIES:
|
||||||
|
:CREATED: [2026-05-17 sun 14:33]
|
||||||
|
:SOURCE: android
|
||||||
|
:ID: phone-20260517-143322-b91c
|
||||||
|
:END:
|
||||||
|
|
||||||
|
mobile capture should stay dumb and append-only.
|
||||||
|
```
|
||||||
|
|
||||||
|
## server paths
|
||||||
|
|
||||||
|
default container paths:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/data/synq.org
|
||||||
|
/data/capture.sqlite3
|
||||||
|
/data/rejected.log
|
||||||
|
```
|
||||||
|
|
||||||
|
recommended host mapping:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/mnt/user/synq/phone-capture:/data
|
||||||
|
```
|
||||||
|
|
||||||
|
or map `/data/synq.org` directly to wherever the real org file lives. prefer a dedicated capture file first; emacs can include it in agenda later.
|
||||||
|
|
||||||
|
## security model
|
||||||
|
|
||||||
|
v1 is lan-only. bind the service to the host lan and do not expose it through swag/cloudflare/public dns.
|
||||||
|
|
||||||
|
minimum useful controls:
|
||||||
|
|
||||||
|
- shared bearer token in app and server env
|
||||||
|
- server only accepts json
|
||||||
|
- server rejects empty body
|
||||||
|
- server dedupes ids
|
||||||
|
- server writes append-only org
|
||||||
|
- server never edits or parses existing org
|
||||||
|
- docker volume is backed up
|
||||||
|
|
||||||
|
## repo layout
|
||||||
|
|
||||||
|
suggested monorepo:
|
||||||
|
|
||||||
|
```text
|
||||||
|
synq/
|
||||||
|
android/
|
||||||
|
app/
|
||||||
|
server/
|
||||||
|
app/
|
||||||
|
main.py
|
||||||
|
models.py
|
||||||
|
org_writer.py
|
||||||
|
store.py
|
||||||
|
tests/
|
||||||
|
Dockerfile
|
||||||
|
pyproject.toml
|
||||||
|
docs/
|
||||||
|
api.md
|
||||||
|
android-notes.md
|
||||||
|
server-notes.md
|
||||||
|
docker-compose.example.yml
|
||||||
|
.env.example
|
||||||
|
tasks.org
|
||||||
|
README.md
|
||||||
|
```
|
||||||
|
## build order
|
||||||
|
|
||||||
|
1. implement server first using curl tests.
|
||||||
|
2. implement android local capture with room.
|
||||||
|
3. implement manual sync.
|
||||||
|
4. add workmanager opportunistic sync.
|
||||||
|
5. add history screen and resend handling.
|
||||||
|
6. polish launch speed and widget/share-target only after core path works.
|
||||||
|
|
||||||
|
## non-goals
|
||||||
|
- no org parser on android
|
||||||
|
- no agenda on android
|
||||||
|
- no sync provider dependency
|
||||||
|
- no nextcloud file editing
|
||||||
|
- no conflict resolution
|
||||||
|
- no public internet exposure
|
||||||
|
- no ai tagging in v1
|
||||||
|
- no account system in v1
|
||||||
|
|
||||||
|
|
||||||
|
## backup
|
||||||
|
|
||||||
|
### what to back up
|
||||||
|
|
||||||
|
the server writes to one directory (the `/data` volume). back up the whole thing:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/data/synq.org ← the canonical org capture file
|
||||||
|
/data/capture.sqlite3 ← idempotency store (dedup ids)
|
||||||
|
/data/token.txt ← auto-generated token (if not using PHONE_CAPTURE_TOKEN env var)
|
||||||
|
```
|
||||||
|
|
||||||
|
on unraid the host path is whatever you mapped in compose, e.g. `/mnt/user/ben/synq/phone-capture`.
|
||||||
|
|
||||||
|
### restore behavior
|
||||||
|
|
||||||
|
- restore the `/data` volume to a new container and start it. the server will pick up where it left off.
|
||||||
|
- `synq.org` is append-only plain text — it is human-readable and recoverable even without the sqlite db.
|
||||||
|
- if `capture.sqlite3` is lost but `synq.org` is intact, the server will accept re-posted captures that were already in the org file (no dedup). the android app marks them synced either way (`already_seen` or `accepted`), so the only side effect is duplicate org entries for anything re-synced. restore the db from backup to avoid this.
|
||||||
|
- if `token.txt` is lost, delete it and let the server generate a new one on next start, then update the app settings.
|
||||||
BIN
logo/icon-bg-512.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
85
logo/icon-bg-512.svg
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<title
|
||||||
|
id="title4">synq</title>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<rect
|
||||||
|
style="display:inline;fill:#22569d;fill-opacity:1;stroke-width:1.00157;stroke-dasharray:none"
|
||||||
|
id="rect5"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="0"
|
||||||
|
y="0.95533592" />
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
style="display:none">
|
||||||
|
<path
|
||||||
|
id="rect6"
|
||||||
|
style="fill:#ffffff;stroke:none;stroke-width:2.90698"
|
||||||
|
d="m 189.13953,130.52304 h 133.72094 c 7.24709,0 13.08139,5.8343 13.08139,13.0814 v 220.93022 c 0,7.2471 -5.8343,13.0814 -13.08139,13.0814 H 189.13953 c -7.24709,0 -13.08139,-5.8343 -13.08139,-13.0814 V 143.60444 c 0,-7.2471 5.8343,-13.0814 13.08139,-13.0814 z" />
|
||||||
|
<path
|
||||||
|
id="rect8"
|
||||||
|
style="display:inline;stroke:#000000;stroke-width:2.90698"
|
||||||
|
d="m 222.26527,361.685 h 66.86046 c 1.61047,0 2.90698,1.29651 2.90698,2.90697 0,1.61047 -1.29651,2.90698 -2.90698,2.90698 h -66.86046 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90698 0,-1.61046 1.29651,-2.90697 2.90698,-2.90697 z" />
|
||||||
|
<path
|
||||||
|
id="rect9"
|
||||||
|
style="display:inline;fill:#22569d;stroke:none;stroke-width:2.90698"
|
||||||
|
d="M 193.63011,145.02974 H 318.6301 c 1.61047,0 2.90698,1.29651 2.90698,2.90698 v 197.67442 c 0,1.61046 -1.29651,2.90697 -2.90698,2.90697 H 193.63011 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90697 V 147.93672 c 0,-1.61047 1.29651,-2.90698 2.90698,-2.90698 z" />
|
||||||
|
<g
|
||||||
|
id="text10"
|
||||||
|
style="font-size:46.5116px;line-height:1.25;letter-spacing:0px;word-spacing:0px;stroke-width:0.726744"
|
||||||
|
aria-label="[X].. [X].. [ ].. ">
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;fill:#00e219"
|
||||||
|
d="m 210.24567,196.0705 h -11.1964 v -42.19656 h 11.1964 v 3.1795 h -7.42642 v 35.83755 h 7.42642 z m 31.56793,-9.31141 h -5.10992 l -7.22201,-11.99127 -7.24473,11.99127 h -5.04178 l 9.87917,-15.17077 -9.0843,-14.51217 h 4.79197 l 6.79051,11.17369 6.83593,-11.17369 h 4.65571 l -9.10701,14.33048 z m 18.28215,9.31141 h -11.1964 v -3.17951 h 7.38099 v -35.83755 h -7.38099 v -3.1795 h 11.1964 z m 20.43967,-16.46529 q 0.77216,0 1.45348,0.29524 0.70404,0.29524 1.20367,0.81759 0.52235,0.52234 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68132 -0.81759,1.20367 -0.49963,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49964,-0.52235 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70404 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29524 1.4762,-0.29524 z m 25.57229,0 q 0.77217,0 1.45349,0.29524 0.70403,0.29524 1.20367,0.81759 0.52235,0.52234 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68132 -0.81759,1.20367 -0.49964,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49963,-0.52235 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70404 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29524 1.4762,-0.29524 z"
|
||||||
|
id="path16" />
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;fill:#00e219"
|
||||||
|
d="m 210.24567,256.17276 h -11.1964 V 213.9762 h 11.1964 v 3.17951 h -7.42642 v 35.83755 h 7.42642 z m 31.56793,-9.3114 h -5.10992 l -7.22201,-11.99128 -7.24473,11.99128 h -5.04178 l 9.87917,-15.17078 -9.0843,-14.51216 h 4.79197 l 6.79051,11.17368 6.83593,-11.17368 h 4.65571 l -9.10701,14.33047 z m 18.28215,9.3114 h -11.1964 v -3.1795 h 7.38099 v -35.83755 h -7.38099 v -3.17951 h 11.1964 z m 20.43967,-16.46529 q 0.77216,0 1.45348,0.29524 0.70404,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68133 -0.81759,1.20367 -0.49963,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49964,-0.52234 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29524 1.4762,-0.29524 z m 25.57229,0 q 0.77217,0 1.45349,0.29524 0.70403,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68133 -0.81759,1.20367 -0.49964,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49963,-0.52234 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29524 1.4762,-0.29524 z"
|
||||||
|
id="path17" />
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;display:inline;fill:#00e219"
|
||||||
|
d="m 210.24567,316.27502 h -11.1964 v -42.19656 h 11.1964 v 3.17951 h -7.42642 v 35.83755 h 7.42642 z m 49.85008,0 h -11.1964 v -3.1795 h 7.38099 v -35.83755 h -7.38099 v -3.17951 h 11.1964 z m 20.43967,-16.46528 q 0.77216,0 1.45348,0.29523 0.70404,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77217 -0.29524,1.45349 -0.29524,0.68132 -0.81759,1.20367 -0.49963,0.49963 -1.20367,0.79487 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79487 -0.49964,-0.52235 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45349 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29523 1.4762,-0.29523 z m 25.57229,0 q 0.77217,0 1.45349,0.29523 0.70403,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77217 -0.29524,1.45349 -0.29524,0.68132 -0.81759,1.20367 -0.49964,0.49963 -1.20367,0.79487 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79487 -0.49963,-0.52235 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45349 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29523 1.4762,-0.29523 z"
|
||||||
|
id="path18" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="layer2"
|
||||||
|
style="display:none;opacity:0.355">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect15"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
<circle
|
||||||
|
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path15"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="256" />
|
||||||
|
</g>
|
||||||
|
<metadata
|
||||||
|
id="metadata4">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:title>synq</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.1 KiB |
BIN
logo/icon-fg-ns-512.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
85
logo/icon-fg-ns-512.svg
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<title
|
||||||
|
id="title4">synq</title>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<rect
|
||||||
|
style="display:inline;fill:#22569d;fill-opacity:1;stroke-width:1.00157;stroke-dasharray:none"
|
||||||
|
id="rect5"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="0"
|
||||||
|
y="0.95533592" />
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="rect6"
|
||||||
|
style="fill:#ffffff;stroke:none;stroke-width:2.90698"
|
||||||
|
d="m 189.13953,130.52304 h 133.72094 c 7.24709,0 13.08139,5.8343 13.08139,13.0814 v 220.93022 c 0,7.2471 -5.8343,13.0814 -13.08139,13.0814 H 189.13953 c -7.24709,0 -13.08139,-5.8343 -13.08139,-13.0814 V 143.60444 c 0,-7.2471 5.8343,-13.0814 13.08139,-13.0814 z" />
|
||||||
|
<path
|
||||||
|
id="rect8"
|
||||||
|
style="display:inline;stroke:#000000;stroke-width:2.90698"
|
||||||
|
d="m 222.26527,361.685 h 66.86046 c 1.61047,0 2.90698,1.29651 2.90698,2.90697 0,1.61047 -1.29651,2.90698 -2.90698,2.90698 h -66.86046 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90698 0,-1.61046 1.29651,-2.90697 2.90698,-2.90697 z" />
|
||||||
|
<path
|
||||||
|
id="rect9"
|
||||||
|
style="display:inline;fill:#22569d;stroke:none;stroke-width:2.90698"
|
||||||
|
d="M 193.63011,145.02974 H 318.6301 c 1.61047,0 2.90698,1.29651 2.90698,2.90698 v 197.67442 c 0,1.61046 -1.29651,2.90697 -2.90698,2.90697 H 193.63011 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90697 V 147.93672 c 0,-1.61047 1.29651,-2.90698 2.90698,-2.90698 z" />
|
||||||
|
<g
|
||||||
|
id="text10"
|
||||||
|
style="font-size:46.5116px;line-height:1.25;letter-spacing:0px;word-spacing:0px;stroke-width:0.726744"
|
||||||
|
aria-label="[X].. [X].. [ ].. ">
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;fill:#00e219"
|
||||||
|
d="m 210.24567,196.0705 h -11.1964 v -42.19656 h 11.1964 v 3.1795 h -7.42642 v 35.83755 h 7.42642 z m 31.56793,-9.31141 h -5.10992 l -7.22201,-11.99127 -7.24473,11.99127 h -5.04178 l 9.87917,-15.17077 -9.0843,-14.51217 h 4.79197 l 6.79051,11.17369 6.83593,-11.17369 h 4.65571 l -9.10701,14.33048 z m 18.28215,9.31141 h -11.1964 v -3.17951 h 7.38099 v -35.83755 h -7.38099 v -3.1795 h 11.1964 z m 20.43967,-16.46529 q 0.77216,0 1.45348,0.29524 0.70404,0.29524 1.20367,0.81759 0.52235,0.52234 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68132 -0.81759,1.20367 -0.49963,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49964,-0.52235 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70404 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29524 1.4762,-0.29524 z m 25.57229,0 q 0.77217,0 1.45349,0.29524 0.70403,0.29524 1.20367,0.81759 0.52235,0.52234 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68132 -0.81759,1.20367 -0.49964,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49963,-0.52235 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70404 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29524 1.4762,-0.29524 z"
|
||||||
|
id="path16" />
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;fill:#00e219"
|
||||||
|
d="m 210.24567,256.17276 h -11.1964 V 213.9762 h 11.1964 v 3.17951 h -7.42642 v 35.83755 h 7.42642 z m 31.56793,-9.3114 h -5.10992 l -7.22201,-11.99128 -7.24473,11.99128 h -5.04178 l 9.87917,-15.17078 -9.0843,-14.51216 h 4.79197 l 6.79051,11.17368 6.83593,-11.17368 h 4.65571 l -9.10701,14.33047 z m 18.28215,9.3114 h -11.1964 v -3.1795 h 7.38099 v -35.83755 h -7.38099 v -3.17951 h 11.1964 z m 20.43967,-16.46529 q 0.77216,0 1.45348,0.29524 0.70404,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68133 -0.81759,1.20367 -0.49963,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49964,-0.52234 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29524 1.4762,-0.29524 z m 25.57229,0 q 0.77217,0 1.45349,0.29524 0.70403,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77216 -0.29524,1.45348 -0.29524,0.68133 -0.81759,1.20367 -0.49964,0.49964 -1.20367,0.79488 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79488 -0.49963,-0.52234 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45348 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29524 1.4762,-0.29524 z"
|
||||||
|
id="path17" />
|
||||||
|
<path
|
||||||
|
style="font-family:Consolas;-inkscape-font-specification:Consolas;display:inline;fill:#00e219"
|
||||||
|
d="m 210.24567,316.27502 h -11.1964 v -42.19656 h 11.1964 v 3.17951 h -7.42642 v 35.83755 h 7.42642 z m 49.85008,0 h -11.1964 v -3.1795 h 7.38099 v -35.83755 h -7.38099 v -3.17951 h 11.1964 z m 20.43967,-16.46528 q 0.77216,0 1.45348,0.29523 0.70404,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77217 -0.29524,1.45349 -0.29524,0.68132 -0.81759,1.20367 -0.49963,0.49963 -1.20367,0.79487 -0.68132,0.29524 -1.45348,0.29524 -0.79488,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79487 -0.49964,-0.52235 -0.79488,-1.20367 -0.29524,-0.68132 -0.29524,-1.45349 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79488,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68132,-0.29523 1.4762,-0.29523 z m 25.57229,0 q 0.77217,0 1.45349,0.29523 0.70403,0.29524 1.20367,0.81759 0.52235,0.52235 0.81759,1.22638 0.29524,0.68132 0.29524,1.4762 0,0.77217 -0.29524,1.45349 -0.29524,0.68132 -0.81759,1.20367 -0.49964,0.49963 -1.20367,0.79487 -0.68132,0.29524 -1.45349,0.29524 -0.79487,0 -1.4762,-0.29524 -0.68132,-0.29524 -1.20367,-0.79487 -0.49963,-0.52235 -0.79487,-1.20367 -0.29524,-0.68132 -0.29524,-1.45349 0,-0.79488 0.29524,-1.4762 0.29524,-0.70403 0.79487,-1.22638 0.52235,-0.52235 1.20367,-0.81759 0.68133,-0.29523 1.4762,-0.29523 z"
|
||||||
|
id="path18" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="layer2"
|
||||||
|
style="display:none;opacity:0.355">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect15"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
<circle
|
||||||
|
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path15"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="256" />
|
||||||
|
</g>
|
||||||
|
<metadata
|
||||||
|
id="metadata4">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:title>synq</dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -9,7 +9,7 @@
|
|||||||
id="svg1"
|
id="svg1"
|
||||||
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||||
sodipodi:docname="icon.svg"
|
sodipodi:docname="icon.svg"
|
||||||
inkscape:export-filename="icon-fg-512.svg"
|
inkscape:export-filename="icon-fg-ns-512.svg"
|
||||||
inkscape:export-xdpi="96"
|
inkscape:export-xdpi="96"
|
||||||
inkscape:export-ydpi="96"
|
inkscape:export-ydpi="96"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
@@ -33,14 +33,14 @@
|
|||||||
inkscape:document-units="px"
|
inkscape:document-units="px"
|
||||||
showgrid="true"
|
showgrid="true"
|
||||||
inkscape:zoom="1.4803312"
|
inkscape:zoom="1.4803312"
|
||||||
inkscape:cx="260.07693"
|
inkscape:cx="259.73917"
|
||||||
inkscape:cy="252.98392"
|
inkscape:cy="253.65945"
|
||||||
inkscape:window-width="1620"
|
inkscape:window-width="1620"
|
||||||
inkscape:window-height="1068"
|
inkscape:window-height="1068"
|
||||||
inkscape:window-x="1935"
|
inkscape:window-x="1979"
|
||||||
inkscape:window-y="192"
|
inkscape:window-y="146"
|
||||||
inkscape:window-maximized="0"
|
inkscape:window-maximized="0"
|
||||||
inkscape:current-layer="layer1">
|
inkscape:current-layer="svg1">
|
||||||
<inkscape:grid
|
<inkscape:grid
|
||||||
id="grid1"
|
id="grid1"
|
||||||
units="px"
|
units="px"
|
||||||
@@ -77,23 +77,22 @@
|
|||||||
only_selected="false"
|
only_selected="false"
|
||||||
hide_knots="false" />
|
hide_knots="false" />
|
||||||
</defs>
|
</defs>
|
||||||
<g
|
|
||||||
inkscape:label="icon"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1">
|
|
||||||
<rect
|
<rect
|
||||||
style="display:none;fill:#22569d;fill-opacity:1;stroke-width:1.00157;stroke-dasharray:none"
|
style="display:inline;fill:#22569d;fill-opacity:1;stroke-width:1.00157;stroke-dasharray:none"
|
||||||
id="rect5"
|
id="rect5"
|
||||||
width="512"
|
width="512"
|
||||||
height="512"
|
height="512"
|
||||||
x="0"
|
x="0"
|
||||||
y="0.95533592"
|
y="0.95533592"
|
||||||
rx="96"
|
|
||||||
ry="96"
|
|
||||||
inkscape:label="bg" />
|
inkscape:label="bg" />
|
||||||
|
<g
|
||||||
|
inkscape:label="icon"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
<path
|
<path
|
||||||
id="rect6"
|
id="rect6"
|
||||||
style="fill:#ffffff;stroke:#000000;stroke-width:2.90698"
|
style="fill:#ffffff;stroke:none;stroke-width:2.90698"
|
||||||
inkscape:label="phone"
|
inkscape:label="phone"
|
||||||
d="m 189.13953,130.52304 h 133.72094 c 7.24709,0 13.08139,5.8343 13.08139,13.0814 v 220.93022 c 0,7.2471 -5.8343,13.0814 -13.08139,13.0814 H 189.13953 c -7.24709,0 -13.08139,-5.8343 -13.08139,-13.0814 V 143.60444 c 0,-7.2471 5.8343,-13.0814 13.08139,-13.0814 z" />
|
d="m 189.13953,130.52304 h 133.72094 c 7.24709,0 13.08139,5.8343 13.08139,13.0814 v 220.93022 c 0,7.2471 -5.8343,13.0814 -13.08139,13.0814 H 189.13953 c -7.24709,0 -13.08139,-5.8343 -13.08139,-13.0814 V 143.60444 c 0,-7.2471 5.8343,-13.0814 13.08139,-13.0814 z" />
|
||||||
<path
|
<path
|
||||||
@@ -103,7 +102,7 @@
|
|||||||
d="m 222.26527,361.685 h 66.86046 c 1.61047,0 2.90698,1.29651 2.90698,2.90697 0,1.61047 -1.29651,2.90698 -2.90698,2.90698 h -66.86046 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90698 0,-1.61046 1.29651,-2.90697 2.90698,-2.90697 z" />
|
d="m 222.26527,361.685 h 66.86046 c 1.61047,0 2.90698,1.29651 2.90698,2.90697 0,1.61047 -1.29651,2.90698 -2.90698,2.90698 h -66.86046 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90698 0,-1.61046 1.29651,-2.90697 2.90698,-2.90697 z" />
|
||||||
<path
|
<path
|
||||||
id="rect9"
|
id="rect9"
|
||||||
style="display:inline;fill:#22569d;stroke:#000000;stroke-width:2.90698"
|
style="display:inline;fill:#22569d;stroke:none;stroke-width:2.90698"
|
||||||
inkscape:label="phone-screen"
|
inkscape:label="phone-screen"
|
||||||
d="M 193.63011,145.02974 H 318.6301 c 1.61047,0 2.90698,1.29651 2.90698,2.90698 v 197.67442 c 0,1.61046 -1.29651,2.90697 -2.90698,2.90697 H 193.63011 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90697 V 147.93672 c 0,-1.61047 1.29651,-2.90698 2.90698,-2.90698 z" />
|
d="M 193.63011,145.02974 H 318.6301 c 1.61047,0 2.90698,1.29651 2.90698,2.90698 v 197.67442 c 0,1.61046 -1.29651,2.90697 -2.90698,2.90697 H 193.63011 c -1.61047,0 -2.90698,-1.29651 -2.90698,-2.90697 V 147.93672 c 0,-1.61047 1.29651,-2.90698 2.90698,-2.90698 z" />
|
||||||
<g
|
<g
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.1 KiB |