Compare commits
13 Commits
4597f92d93
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 62c9b8e59d | |||
| a4591655b7 | |||
| 5a7542fb4c | |||
| 9989d81b51 | |||
| 7e0e7e4c29 | |||
| 28d96bd3c1 | |||
| adc7fb54d9 | |||
| 4adca319be | |||
| 1d31556923 | |||
| 628a28a775 | |||
| fca3ea6f60 | |||
| 68deb5cb3e | |||
| edd2c1745f |
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 |
@@ -4,6 +4,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.navigation.NavType
|
import androidx.navigation.NavType
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
@@ -20,6 +21,7 @@ import java.net.URLEncoder
|
|||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
enableEdgeToEdge()
|
||||||
val sharedText = if (intent.action == Intent.ACTION_SEND)
|
val sharedText = if (intent.action == Intent.ACTION_SEND)
|
||||||
intent.getStringExtra(Intent.EXTRA_TEXT) else null
|
intent.getStringExtra(Intent.EXTRA_TEXT) else null
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package me.hgsky.synq.data
|
package me.hgsky.synq.data
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.intPreferencesKey
|
import androidx.datastore.preferences.core.intPreferencesKey
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
@@ -28,7 +30,10 @@ class SettingsRepository(private val context: Context) {
|
|||||||
SynqSettings(
|
SynqSettings(
|
||||||
serverUrl = prefs[KEY_URL] ?: "http://jeeves.mother:8765",
|
serverUrl = prefs[KEY_URL] ?: "http://jeeves.mother:8765",
|
||||||
token = prefs[KEY_TOKEN] ?: "",
|
token = prefs[KEY_TOKEN] ?: "",
|
||||||
deviceLabel = prefs[KEY_DEVICE] ?: "android",
|
deviceLabel = prefs[KEY_DEVICE] ?: (
|
||||||
|
Settings.Global.getString(context.contentResolver, Settings.Global.DEVICE_NAME)
|
||||||
|
?.takeIf { it.isNotBlank() } ?: Build.MODEL
|
||||||
|
),
|
||||||
syncIntervalMinutes = prefs[KEY_INTERVAL] ?: 15,
|
syncIntervalMinutes = prefs[KEY_INTERVAL] ?: 15,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ fun CaptureScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(snackbarState) },
|
snackbarHost = { SnackbarHost(snackbarState, modifier = Modifier.imePadding()) },
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = { Text("synq") },
|
title = { Text("synq") },
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
package me.hgsky.synq.ui.theme
|
package me.hgsky.synq.ui.theme
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SynqTheme(content: @Composable () -> Unit) {
|
fun SynqTheme(content: @Composable () -> Unit) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val colorScheme = dynamicLightColorScheme(context)
|
val colorScheme = dynamicLightColorScheme(context)
|
||||||
|
|
||||||
|
val view = LocalView.current
|
||||||
|
if (!view.isInEditMode) {
|
||||||
|
SideEffect {
|
||||||
|
val window = (view.context as Activity).window
|
||||||
|
// light theme → dark icons so clock/battery/wifi are visible on light TopAppBar
|
||||||
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MaterialTheme(colorScheme = colorScheme, content = content)
|
MaterialTheme(colorScheme = colorScheme, content = content)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
android:pathData="M0,0.96h512v512h-512z"
|
||||||
|
android:strokeWidth="1.00157"
|
||||||
|
android:fillColor="#22569d"/>
|
||||||
<path
|
<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.
|
||||||
86
logo/icon-512.svg
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?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" />
|
||||||
|
<g
|
||||||
|
id="layer1">
|
||||||
|
<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"
|
||||||
|
rx="96"
|
||||||
|
ry="96" />
|
||||||
|
<path
|
||||||
|
id="rect6"
|
||||||
|
style="fill:#ffffff;stroke:#000000;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:#000000;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.2 KiB |
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 |
86
logo/icon-fg-512.svg
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?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" />
|
||||||
|
<g
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="display:none;fill:#22569d;fill-opacity:1;stroke-width:1.00157;stroke-dasharray:none"
|
||||||
|
id="rect5"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
x="0"
|
||||||
|
y="0.95533592"
|
||||||
|
rx="96"
|
||||||
|
ry="96" />
|
||||||
|
<path
|
||||||
|
id="rect6"
|
||||||
|
style="fill:#ffffff;stroke:#000000;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:#000000;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.2 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 |
154
logo/icon.svg
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?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"
|
||||||
|
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||||
|
sodipodi:docname="icon.svg"
|
||||||
|
inkscape:export-filename="icon-fg-ns-512.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
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>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="true"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="1.4803312"
|
||||||
|
inkscape:cx="259.73917"
|
||||||
|
inkscape:cy="253.65945"
|
||||||
|
inkscape:window-width="1620"
|
||||||
|
inkscape:window-height="1068"
|
||||||
|
inkscape:window-x="1979"
|
||||||
|
inkscape:window-y="146"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg1">
|
||||||
|
<inkscape:grid
|
||||||
|
id="grid1"
|
||||||
|
units="px"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="4.2333333"
|
||||||
|
spacingy="4.2333333"
|
||||||
|
empcolor="#3f3fff"
|
||||||
|
empopacity="0.25098039"
|
||||||
|
color="#3f3fff"
|
||||||
|
opacity="0.1254902"
|
||||||
|
empspacing="5"
|
||||||
|
enabled="true"
|
||||||
|
visible="true"
|
||||||
|
dotted="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="fillet_chamfer"
|
||||||
|
id="path-effect5"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||||
|
radius="0"
|
||||||
|
unit="px"
|
||||||
|
method="auto"
|
||||||
|
mode="F"
|
||||||
|
chamfer_steps="1"
|
||||||
|
flexible="false"
|
||||||
|
use_knot_distance="true"
|
||||||
|
apply_no_radius="true"
|
||||||
|
apply_with_radius="true"
|
||||||
|
only_selected="false"
|
||||||
|
hide_knots="false" />
|
||||||
|
</defs>
|
||||||
|
<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"
|
||||||
|
inkscape:label="bg" />
|
||||||
|
<g
|
||||||
|
inkscape:label="icon"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<path
|
||||||
|
id="rect6"
|
||||||
|
style="fill:#ffffff;stroke:none;stroke-width:2.90698"
|
||||||
|
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" />
|
||||||
|
<path
|
||||||
|
id="rect8"
|
||||||
|
style="display:inline;stroke:#000000;stroke-width:2.90698"
|
||||||
|
inkscape:label="phone-navbar"
|
||||||
|
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"
|
||||||
|
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" />
|
||||||
|
<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
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="circle-mask"
|
||||||
|
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: 9.1 KiB |
@@ -48,7 +48,7 @@ def _load_token() -> str:
|
|||||||
logger.info("synq token loaded from %s", token_file)
|
logger.info("synq token loaded from %s", token_file)
|
||||||
return _token_cache
|
return _token_cache
|
||||||
|
|
||||||
generated = secrets.token_hex(32)
|
generated = _generate_passphrase()
|
||||||
token_file.parent.mkdir(parents=True, exist_ok=True)
|
token_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
token_file.write_text(generated)
|
token_file.write_text(generated)
|
||||||
logger.info("")
|
logger.info("")
|
||||||
@@ -61,6 +61,72 @@ def _load_token() -> str:
|
|||||||
return _token_cache
|
return _token_cache
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_passphrase(words: int = 3) -> str:
|
||||||
|
wordlist = [
|
||||||
|
"able","acid","aged","also","area","army","away","baby","back","ball",
|
||||||
|
"band","bank","base","bath","bear","beat","been","bell","best","bill",
|
||||||
|
"bird","blow","blue","bold","bolt","bone","book","born","both","bowl",
|
||||||
|
"bulk","burn","calm","came","card","care","cart","case","cash","cast",
|
||||||
|
"cave","cell","chat","chip","city","clam","clay","clip","club","coal",
|
||||||
|
"coat","code","coil","cold","come","cook","cool","cope","cord","core",
|
||||||
|
"corn","cost","cove","crew","crop","curl","dare","dark","data","date",
|
||||||
|
"dawn","days","dead","deal","dean","dear","deck","deep","deer","deft",
|
||||||
|
"deny","desk","dial","diet","disc","dish","disk","dive","dock","dome",
|
||||||
|
"door","dose","down","draw","drew","drip","drop","drum","dual","dusk",
|
||||||
|
"dust","duty","each","earn","ease","east","edge","else","even","ever",
|
||||||
|
"evil","exam","fact","fail","fair","fall","fame","farm","fast","fate",
|
||||||
|
"feed","feel","feet","fell","felt","file","fill","film","find","fire",
|
||||||
|
"firm","fish","fist","flag","flat","flew","flip","flow","foam","fold",
|
||||||
|
"folk","fond","font","food","foot","ford","fork","form","fort","free",
|
||||||
|
"from","fuel","full","fund","fuse","gain","game","gaze","gear","give",
|
||||||
|
"glad","glow","glue","goal","gold","golf","gone","good","grab","gray",
|
||||||
|
"grid","grim","grip","grow","gulf","gust","hack","hail","half","hall",
|
||||||
|
"halt","hand","hang","hard","harm","harp","hash","haul","have","hawk",
|
||||||
|
"head","heal","heap","heat","heel","held","helm","help","herb","here",
|
||||||
|
"hide","high","hill","hint","hold","hole","home","hook","hope","horn",
|
||||||
|
"host","hour","hull","hunt","hurt","icon","idea","idle","inch","into",
|
||||||
|
"iris","iron","isle","item","jade","jail","jazz","jest","join","jump",
|
||||||
|
"just","keen","keep","kelp","kern","keys","kick","kill","kind","king",
|
||||||
|
"knit","know","lack","lake","lamp","land","lane","lark","lash","last",
|
||||||
|
"late","lead","leaf","lean","leap","left","lend","lens","life","lift",
|
||||||
|
"like","lime","line","link","lion","list","live","load","loan","lock",
|
||||||
|
"loft","long","look","loop","lore","loss","loud","love","luck","lung",
|
||||||
|
"lure","mail","main","make","male","malt","many","mark","mask","mast",
|
||||||
|
"math","maze","meal","mean","meet","melt","mesh","mild","milk","mill",
|
||||||
|
"mind","mine","mint","miss","mist","mode","moon","more","moss","most",
|
||||||
|
"move","much","mule","must","nail","name","navy","near","neat","need",
|
||||||
|
"nest","news","next","nice","node","none","noon","norm","note","null",
|
||||||
|
"numb","oath","obey","odds","once","only","open","oral","over","pace",
|
||||||
|
"pack","page","paid","pain","pair","palm","park","part","pass","past",
|
||||||
|
"path","pave","peak","peel","peer","pick","pier","pile","pine","pipe",
|
||||||
|
"plan","play","plea","plot","plow","plum","plunge","plus","poem","poet",
|
||||||
|
"pole","poll","pond","pool","port","pose","post","pour","prey","pull",
|
||||||
|
"pump","pure","push","quit","race","rack","raid","rail","rain","ramp",
|
||||||
|
"rang","rank","rare","rate","read","real","reed","reel","rely","rent",
|
||||||
|
"rest","rice","rich","ride","ring","rise","risk","road","roam","roar",
|
||||||
|
"rock","role","roll","roof","root","rope","rose","rout","rule","rush",
|
||||||
|
"rust","safe","sage","sail","salt","same","sand","sang","save","scan",
|
||||||
|
"seal","seam","seed","seek","self","sell","send","sent","shed","ship",
|
||||||
|
"shop","shot","show","shut","sick","side","sign","silk","sing","sink",
|
||||||
|
"site","size","skip","slab","slam","slap","slim","slip","slot","slow",
|
||||||
|
"snap","snow","soak","soar","sock","soil","sold","sole","some","song",
|
||||||
|
"soon","sort","soul","soup","span","spin","spit","spot","spur","star",
|
||||||
|
"stay","stem","step","stop","stub","such","suit","sunk","sure","surf",
|
||||||
|
"swap","swim","tail","take","talk","tall","tank","tape","task","team",
|
||||||
|
"tell","tend","tent","term","test","text","than","then","thin","tide",
|
||||||
|
"tile","time","tint","tiny","tips","tire","toad","told","toll","tomb",
|
||||||
|
"tool","tops","toss","tour","town","trap","tree","trim","trip","trod",
|
||||||
|
"true","tube","tuck","tune","turf","turn","twin","type","upon","used",
|
||||||
|
"vary","vast","veil","vein","very","vest","view","vine","void","volt",
|
||||||
|
"vote","wade","wake","walk","wall","wand","ward","warm","warp","wary",
|
||||||
|
"wave","ways","weld","well","went","west","what","when","wide","wiki",
|
||||||
|
"wild","will","wind","wine","wire","wise","wish","with","wolf","wood",
|
||||||
|
"word","work","worn","wrap","wren","yard","year","yell","your","zero",
|
||||||
|
"zest","zinc","zone","zoom",
|
||||||
|
]
|
||||||
|
return "-".join(secrets.choice(wordlist) for _ in range(words))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_store() -> IdempotencyStore:
|
def get_store() -> IdempotencyStore:
|
||||||
global _store
|
global _store
|
||||||
|
|||||||
82
tasks.org
@@ -471,6 +471,88 @@ SynqSettings gained syncIntervalMinutes: Int = 15 field with DataStore key sync_
|
|||||||
- tests: manual — change interval to 30, save, verify WorkManager re-queues (check adb shell dumpsys jobscheduler)
|
- tests: manual — change interval to 30, save, verify WorkManager re-queues (check adb shell dumpsys jobscheduler)
|
||||||
- datetime: [2026-05-18 Sun 20:00]
|
- datetime: [2026-05-18 Sun 20:00]
|
||||||
|
|
||||||
|
* milestone 6: post-ship cleanup
|
||||||
|
** DONE fix resource XML comment before <?xml declaration
|
||||||
|
*** acceptance
|
||||||
|
- android build succeeds with custom icon assets.
|
||||||
|
*** notes
|
||||||
|
Android's AAPT resource compiler requires <?xml to be the first byte of the file. Image Asset tool generated ic_launcher_background.xml, ic_launcher.xml, and ic_launcher_round.xml with an Apache license comment block before <?xml, causing ParseError at row 16. Fixed by stripping the comment from those three files. ic_launcher_foreground.xml was unaffected (no <?xml declaration). Do not use Image Asset tool for tweaks — it re-adds the comment on reimport; edit XML directly.
|
||||||
|
*** evidence
|
||||||
|
- commit: a6af2fe
|
||||||
|
- tests: manual — gradle assembleDebug succeeds
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE fix manifest missing icon references
|
||||||
|
*** acceptance
|
||||||
|
- app icon appears on device launcher after install.
|
||||||
|
*** notes
|
||||||
|
AndroidManifest.xml was missing android:icon and android:roundIcon attributes on the <application> element. Added @mipmap/ic_launcher and @mipmap/ic_launcher_round. Also committed all mipmap-* webp files and drawable/ic_launcher_background.xml (solid #22569d) and ic_launcher_foreground.xml generated by Image Asset tool.
|
||||||
|
*** evidence
|
||||||
|
- commit: a6af2fe
|
||||||
|
- tests: manual — install APK on device, verify icon appears in launcher
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE fix status bar icons washed out (API 35 edge-to-edge)
|
||||||
|
*** acceptance
|
||||||
|
- system clock, battery, wifi icons are visible over the app TopAppBar.
|
||||||
|
*** notes
|
||||||
|
Android 15 (API 35) enforces edge-to-edge regardless of enableEdgeToEdge() call — removing it had no effect. Real fix: keep enableEdgeToEdge() in MainActivity and add a SideEffect in Theme.kt that calls WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true. This tells the system to render dark (visible) status bar icons on the light TopAppBar background.
|
||||||
|
*** evidence
|
||||||
|
- commit: 68deb5c
|
||||||
|
- tests: manual — open app, verify clock/battery/wifi icons are dark and readable
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE fix keyboard covering Save button
|
||||||
|
*** acceptance
|
||||||
|
- Save and Save & Close buttons are visible above the software keyboard.
|
||||||
|
*** notes
|
||||||
|
Added imePadding() to the Column modifier in CaptureScreen. The column shrinks to fit above the keyboard rather than being obscured by it.
|
||||||
|
*** evidence
|
||||||
|
- commit: 23df95d
|
||||||
|
- tests: manual — tap body field, keyboard opens, verify save buttons remain visible
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE add sync result snackbar
|
||||||
|
*** acceptance
|
||||||
|
- brief snackbar appears after tapping sync: "synced N", "nothing to sync", or "server unreachable".
|
||||||
|
*** notes
|
||||||
|
Added MutableSharedFlow<String> snackbar emitter to CaptureViewModel. syncNow() now calls checkHealth() first and emits "server unreachable" on failure. syncPending() return type changed from Unit to Int (count of successfully synced captures). SnackbarHost added to CaptureScreen Scaffold; LaunchedEffect collects the flow and calls snackbarState.showSnackbar().
|
||||||
|
*** evidence
|
||||||
|
- commit: 4597f92
|
||||||
|
- tests: manual — tap sync with server up (see "synced N"), with server down (see "server unreachable"), with empty queue (see "nothing to sync")
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE log token on every server startup
|
||||||
|
*** acceptance
|
||||||
|
- token is clearly visible in container logs on every start, not just first run.
|
||||||
|
*** notes
|
||||||
|
lifespan() in server/app/main.py now logs the token between === lines on every startup. Previously only logged "token loaded from token.txt" quietly; now logs the token value itself so it's easy to find with docker logs synq.
|
||||||
|
*** evidence
|
||||||
|
- commit: a6af2fe
|
||||||
|
- tests: manual — docker restart synq, docker logs synq | grep token
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE default device label to Build.MODEL
|
||||||
|
*** acceptance
|
||||||
|
- fresh install shows the actual device model name, not "android".
|
||||||
|
*** notes
|
||||||
|
SettingsRepository.kt: changed deviceLabel fallback from hardcoded "android" to Build.MODEL. No permissions needed. Existing users who have already saved a label are unaffected — DataStore only uses the fallback when no value is stored.
|
||||||
|
*** evidence
|
||||||
|
- commit: 628a28a
|
||||||
|
- tests: manual — fresh install, open settings, verify device label shows model name
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
|
** DONE replace hex token with 3-word passphrase
|
||||||
|
*** acceptance
|
||||||
|
- generated token is human-readable and fits on one log line.
|
||||||
|
- existing token.txt files are unaffected.
|
||||||
|
*** notes
|
||||||
|
secrets.token_hex(32) produced 64 chars — too long to read/verify visually. Replaced with _generate_passphrase() which picks 3 words from a 512-word embedded list using secrets.choice, hyphenated (e.g. "coral-drift-lamp"). ~27 bits entropy, sufficient for a LAN-only service. Existing token.txt files load unchanged — generation only runs when no token exists. To rotate: delete /data/token.txt and restart the container.
|
||||||
|
*** evidence
|
||||||
|
- commit: 628a28a
|
||||||
|
- tests: manual — delete token.txt, restart container, docker logs synq shows short readable token
|
||||||
|
- datetime: [2026-05-19 Mon]
|
||||||
|
|
||||||
* implementation notes for coding agents
|
* implementation notes for coding agents
|
||||||
- keep the server small and testable.
|
- keep the server small and testable.
|
||||||
- keep org formatting in one pure function.
|
- keep org formatting in one pure function.
|
||||||
|
|||||||