Compare commits
438 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e588e44c | ||
|
|
083de6418f | ||
|
|
5b9e6e3d48 | ||
|
|
4a6ba38e94 | ||
|
|
4d38ddd341 | ||
|
|
267d2ec9e1 | ||
|
|
526a0c7246 | ||
|
|
95aa1de8a8 | ||
|
|
d8b80c2a97 | ||
|
|
406fa80dd0 | ||
|
|
de1ccc5a2e | ||
|
|
0a479e4517 | ||
|
|
8c59396ec8 | ||
|
|
3647cb125b | ||
|
|
adc122fce0 | ||
|
|
d33ebd8f4c | ||
|
|
06530f36ff | ||
|
|
3cfa0db7e6 | ||
|
|
d9420ff13b | ||
|
|
7e0ba60a22 | ||
|
|
257e26c996 | ||
|
|
dcb374fbf9 | ||
|
|
9c3dae3e7d | ||
|
|
7806efb2cf | ||
|
|
7a21de7cda | ||
|
|
295d4cf2bb | ||
|
|
09ea277a40 | ||
|
|
4fa0745d1b | ||
|
|
a62a068c08 | ||
|
|
5c49af5355 | ||
|
|
e48c575b9d | ||
|
|
e03675168b | ||
|
|
d6a2e263cc | ||
|
|
f638c79e13 | ||
|
|
874e81ab8b | ||
|
|
a5d0008555 | ||
|
|
4d0d6f8565 | ||
|
|
7b1d25e286 | ||
|
|
5adbe2263e | ||
|
|
b1c416d029 | ||
|
|
8305ca588c | ||
|
|
0cf56b6fba | ||
|
|
ecce7f3504 | ||
|
|
17fa183c4f | ||
|
|
5b0a6f5f8b | ||
|
|
2e8b5ad856 | ||
|
|
e32b098be4 | ||
|
|
b45629f13c | ||
|
|
96421c346d | ||
|
|
724b3e14e5 | ||
|
|
e8c83a2774 | ||
|
|
5c5a9df5a6 | ||
|
|
7cb4bbe61b | ||
|
|
fed8b9e124 | ||
|
|
60e734086f | ||
|
|
c3181e9bd5 | ||
|
|
f4fa487b2d | ||
|
|
e0237108c6 | ||
|
|
d7a636251d | ||
|
|
108573b100 | ||
|
|
36f55e6b79 | ||
|
|
b4dd72e7eb | ||
|
|
f5f2e977a1 | ||
|
|
e9a0dc0d59 | ||
|
|
d75c395514 | ||
|
|
b08f951780 | ||
|
|
955431ac18 | ||
|
|
7f40abf92a | ||
|
|
c157fd481b | ||
|
|
a6fc7145bc | ||
|
|
ca05cbb2c5 | ||
|
|
5c79572c4d | ||
|
|
6fd8e5ad12 | ||
|
|
09fbc32e48 | ||
|
|
4591d5acd6 | ||
|
|
6c711f80b4 | ||
|
|
e61e701240 | ||
|
|
42f4e80a26 | ||
|
|
4dc03f33ca | ||
|
|
5572c6cd12 | ||
|
|
4f7e66de82 | ||
|
|
c1898037c0 | ||
|
|
efc5f64279 | ||
|
|
636a203254 | ||
|
|
2e78fa7a3a | ||
|
|
e74f985630 | ||
|
|
e4facd7f26 | ||
|
|
f533362f8a | ||
|
|
175a8f368f | ||
|
|
872bcbd529 | ||
|
|
8811f71e53 | ||
|
|
fec649a159 | ||
|
|
9e3f481401 | ||
|
|
1a497864a7 | ||
|
|
06fb90513f | ||
|
|
b5eecb1ec1 | ||
|
|
0e211aebdd | ||
|
|
96b62d7e14 | ||
|
|
baf6ffff0b | ||
|
|
135de0863c | ||
|
|
074a61baac | ||
|
|
209cc948bf | ||
|
|
cc108f2f49 | ||
|
|
844204f64d | ||
|
|
88f699f4ec | ||
|
|
d1b9196f47 | ||
|
|
8181fc8e03 | ||
|
|
5be2ac417a | ||
|
|
6acb1c833c | ||
|
|
2bd69415c1 | ||
|
|
7160d72aae | ||
|
|
f4aee2aba4 | ||
|
|
a789a9552a | ||
|
|
9fd1401737 | ||
|
|
9ae837582b | ||
|
|
db61a7d626 | ||
|
|
f8d78b5489 | ||
|
|
eaa691808a | ||
|
|
e733a0dd13 | ||
|
|
2ae1e34d63 | ||
|
|
e432c843c3 | ||
|
|
6f2db06f25 | ||
|
|
4946ea1751 | ||
|
|
f8ed75a095 | ||
|
|
2269d9b4ba | ||
|
|
753c0f171f | ||
|
|
8939911ce1 | ||
|
|
356f60d02f | ||
|
|
0067d7834f | ||
|
|
d60d774e73 | ||
|
|
0bb237c4ab | ||
|
|
54fa1759d1 | ||
|
|
134cf92c6d | ||
|
|
f93c14a9c5 | ||
|
|
189548277d | ||
|
|
21cecc970f | ||
|
|
ca4a55312f | ||
|
|
c31bb1ac74 | ||
|
|
ac36db19a7 | ||
|
|
330a990bea | ||
|
|
5c2c2646cc | ||
|
|
eab6af414f | ||
|
|
c55f3a19e9 | ||
|
|
db670fbb7c | ||
|
|
546e009867 | ||
|
|
be46963744 | ||
|
|
8f7adba65a | ||
|
|
e8b38ed65a | ||
|
|
700fcef33f | ||
|
|
b23d864f1d | ||
|
|
e1d43cec57 | ||
|
|
cd7bced827 | ||
|
|
b298f2f22c | ||
|
|
9304a99745 | ||
|
|
4a03e17886 | ||
|
|
e502ddd436 | ||
|
|
12f1801ed2 | ||
|
|
a6a63bf12e | ||
|
|
631455237f | ||
|
|
382e2609c9 | ||
|
|
05efbc5f20 | ||
|
|
9a45430321 | ||
|
|
cb843d5774 | ||
|
|
c823347175 | ||
|
|
d87c0cc226 | ||
|
|
9c957a4a14 | ||
|
|
16442bab08 | ||
|
|
e479983d38 | ||
|
|
70fca17230 | ||
|
|
2107d6790d | ||
|
|
8823b7cb48 | ||
|
|
e40c0d9078 | ||
|
|
8b090cb238 | ||
|
|
2bb8e3fd66 | ||
|
|
deb7263c3e | ||
|
|
3daadc4f68 | ||
|
|
6b72b1b3da | ||
|
|
52486d82ad | ||
|
|
487d618e00 | ||
|
|
9239805129 | ||
|
|
554b2abd82 | ||
|
|
8bb98f65d6 | ||
|
|
71c0f8b21e | ||
|
|
aa2bc68544 | ||
|
|
a8394effdc | ||
|
|
e27d5ab53c | ||
|
|
6af272c01f | ||
|
|
03e2fe6a72 | ||
|
|
87b4cd79e7 | ||
|
|
d94d75e605 | ||
|
|
c965d05229 | ||
|
|
ba80fac36c | ||
|
|
3c2c7611ee | ||
|
|
49e0f39ca9 | ||
|
|
625df7982d | ||
|
|
8eeb13166b | ||
|
|
80645990cb | ||
|
|
96a3bb86e9 | ||
|
|
6775de3cca | ||
|
|
8143fbd8f7 | ||
|
|
cf3949ef95 | ||
|
|
32d9da2865 | ||
|
|
61e8c92f62 | ||
|
|
d954df6294 | ||
|
|
30d535bd43 | ||
|
|
d06aa42ab2 | ||
|
|
108fc93ca1 | ||
|
|
427479c1e6 | ||
|
|
ee05f312e8 | ||
|
|
c4193e38dc | ||
|
|
cb9b081606 | ||
|
|
cc8fec6d05 | ||
|
|
01665b6e3a | ||
|
|
1898a99789 | ||
|
|
3eefda9205 | ||
|
|
a6ba9a8227 | ||
|
|
7055444c4b | ||
|
|
4bfc0e25cb | ||
|
|
81335cbf7b | ||
|
|
76b57c08c6 | ||
|
|
926b5591b0 | ||
|
|
957e597004 | ||
|
|
68cfbf139f | ||
|
|
b2f4fcaaa5 | ||
|
|
dc2fa9d247 | ||
|
|
a32125996c | ||
|
|
506a1ab5f6 | ||
|
|
db7b67d859 | ||
|
|
49f08a7f75 | ||
|
|
b2d35d3edf | ||
|
|
a9d618cdbc | ||
|
|
6a65abd2e3 | ||
|
|
a3aef8cadd | ||
|
|
cff89a8c88 | ||
|
|
26c1366412 | ||
|
|
28f5b49f4d | ||
|
|
a46da284e5 | ||
|
|
22a31b6c80 | ||
|
|
b7ef0bbfcd | ||
|
|
03b5a10fe4 | ||
|
|
e97498d09f | ||
|
|
7db76ec2fc | ||
|
|
63beb2ea6b | ||
|
|
ffad84f18a | ||
|
|
2642ff7a95 | ||
|
|
40b6eda096 | ||
|
|
dee6ad7e4a | ||
|
|
ea9c633eff | ||
|
|
9c73fceea7 | ||
|
|
5133e9d498 | ||
|
|
b63e5328b1 | ||
|
|
d66b09ddee | ||
|
|
009965f2fb | ||
|
|
51e6479ab6 | ||
|
|
874c8fd73c | ||
|
|
e4c48682b0 | ||
|
|
00444f7611 | ||
|
|
511e6d377c | ||
|
|
e6974a683a | ||
|
|
c0d68b23d4 | ||
|
|
ee904633a8 | ||
|
|
4329605e6f | ||
|
|
772c5888c3 | ||
|
|
f04e917cd9 | ||
|
|
9e939194ba | ||
|
|
e328a20929 | ||
|
|
aba94b197d | ||
|
|
80f2bbdb25 | ||
|
|
522213c040 | ||
|
|
58998ba274 | ||
|
|
4ad718e164 | ||
|
|
707786e222 | ||
|
|
868bf08fd1 | ||
|
|
1316d4f2d1 | ||
|
|
9be390ee09 | ||
|
|
d9ed006b4c | ||
|
|
d09fc842b8 | ||
|
|
73bdd809bd | ||
|
|
f1dba89d4b | ||
|
|
131a63845c | ||
|
|
2240be1f2d | ||
|
|
a048a83c6c | ||
|
|
4ef1e29034 | ||
|
|
b21df3de5c | ||
|
|
678af5e55b | ||
|
|
c4fd59626f | ||
|
|
0a26e4252a | ||
|
|
d19e032b40 | ||
|
|
ab9ae796f3 | ||
|
|
0f2f2f447c | ||
|
|
3a031694db | ||
|
|
3cfbffc155 | ||
|
|
4f5aec45b3 | ||
|
|
2acfca20d9 | ||
|
|
f2ed5f5c03 | ||
|
|
db04b85134 | ||
|
|
ba66ac5cea | ||
|
|
a592b655c4 | ||
|
|
a5a2ae5edc | ||
|
|
363b4c5525 | ||
|
|
16e1304ded | ||
|
|
b89347938a | ||
|
|
6969ae6c4a | ||
|
|
64f8862676 | ||
|
|
6660986211 | ||
|
|
5dfcc1a5fe | ||
|
|
2efd28766b | ||
|
|
c9bba25e5a | ||
|
|
41976a3b43 | ||
|
|
5a47a8f8e4 | ||
|
|
c13f3c913f | ||
|
|
2e9b54b6cf | ||
|
|
7e844be627 | ||
|
|
b37e55c29a | ||
|
|
332ba044f2 | ||
|
|
09a2d849ec | ||
|
|
a3fb9b0d5c | ||
|
|
192978acf9 | ||
|
|
581aaea93b | ||
|
|
299752a4f1 | ||
|
|
142c0aa539 | ||
|
|
78168ce3db | ||
|
|
332abbc183 | ||
|
|
c136c5cf26 | ||
|
|
2a65e89eee | ||
|
|
d6f1e7bc80 | ||
|
|
5ac5f3ec3f | ||
|
|
bb4cbfa62c | ||
|
|
f0d600e5d7 | ||
|
|
e0f0a6390d | ||
|
|
d4a27dccf7 | ||
|
|
74c4596dc5 | ||
|
|
1f2328613c | ||
|
|
eeca67f6ea | ||
|
|
4ae8a1cfca | ||
|
|
ff06129a6f | ||
|
|
6d7aa4dd56 | ||
|
|
4548f750d3 | ||
|
|
31f02010d3 | ||
|
|
ec1ea5cbba | ||
|
|
8500c59755 | ||
|
|
556dd6b51c | ||
|
|
3863e2d63d | ||
|
|
9e62621819 | ||
|
|
c8c7c8cc05 | ||
|
|
5116313ab0 | ||
|
|
66389dd27c | ||
|
|
ee6501243f | ||
|
|
8dd912175d | ||
|
|
02f9fb45e2 | ||
|
|
4254dbda91 | ||
|
|
a46bed1c33 | ||
|
|
d711300442 | ||
|
|
98a8203591 | ||
|
|
084c5ae158 | ||
|
|
17018aeb19 | ||
|
|
74b3da6f00 | ||
|
|
ab1217a8bf | ||
|
|
62de1480f7 | ||
|
|
ab2e9b06e1 | ||
|
|
e91ad24cf9 | ||
|
|
2e543b7cd4 | ||
|
|
db4353ccdc | ||
|
|
5a610cf08a | ||
|
|
71b854998c | ||
|
|
0a70ae4b3e | ||
|
|
6e709b0b67 | ||
|
|
a4256cee83 | ||
|
|
89f0b1bcfe | ||
|
|
e8af3b2397 | ||
|
|
812d3c851f | ||
|
|
608d1e0396 | ||
|
|
63787454ca | ||
|
|
55c1384f80 | ||
|
|
6750d7bc12 | ||
|
|
d33fcaf5db | ||
|
|
7974fd9597 | ||
|
|
dcb512636c | ||
|
|
7c6bf801e9 | ||
|
|
71e9f89aae | ||
|
|
0936c6087b | ||
|
|
95e3e8723a | ||
|
|
671a910936 | ||
|
|
3b64e829a8 | ||
|
|
84ed739a61 | ||
|
|
cffdb7dca6 | ||
|
|
4182a9f83c | ||
|
|
9873f6105d | ||
|
|
8d3829cc4e | ||
|
|
e424485761 | ||
|
|
baf7f5d137 | ||
|
|
3edf60c625 | ||
|
|
1beb343501 | ||
|
|
0c0f877b13 | ||
|
|
f7a1b5c5ad | ||
|
|
051d09dcaf | ||
|
|
eb900aecb6 | ||
|
|
f16393eafd | ||
|
|
49dcfebfb3 | ||
|
|
1c13b99f3b | ||
|
|
54a1eb5b42 | ||
|
|
2818c6d2b8 | ||
|
|
f4aa5d3873 | ||
|
|
542f4dd0e2 | ||
|
|
4a72cdda75 | ||
|
|
4b9d581448 | ||
|
|
1d3b3f11e9 | ||
|
|
e97824fd0b | ||
|
|
1cd9058685 | ||
|
|
47e23ea14c | ||
|
|
afd18794c7 | ||
|
|
203bd623bd | ||
|
|
2b6b44a31d | ||
|
|
0059a6aab3 | ||
|
|
fc30a080ff | ||
|
|
7399c02be9 | ||
|
|
02e985d2a8 | ||
|
|
954352809f | ||
|
|
7eb36a5a3d | ||
|
|
0768b4d91a | ||
|
|
be1306c9c0 | ||
|
|
7904717597 | ||
|
|
e2c19e1611 | ||
|
|
b230e79ab0 | ||
|
|
31727e35bb | ||
|
|
22127bbfb4 | ||
|
|
413278544a | ||
|
|
580a588df7 | ||
|
|
b39b83fb51 | ||
|
|
6d948603c9 | ||
|
|
648bcc9b92 | ||
|
|
4dc1227be7 | ||
|
|
3b097feaae | ||
|
|
da2e5fbde1 | ||
|
|
003db7c36a | ||
|
|
9aa640338d | ||
|
|
3c24b71f16 | ||
|
|
eee6738a9c |
20
.codecov.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 100%
|
||||
threshold: 10%
|
||||
76
.dockerignore
Normal file
@@ -0,0 +1,76 @@
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
*.md
|
||||
|
||||
# Docker files
|
||||
docker-compose*.yml
|
||||
.dockerignore
|
||||
|
||||
# Environment files
|
||||
.env*
|
||||
!.env.example
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# Runtime data
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage/
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
vendor/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Test files
|
||||
tests/
|
||||
spec/
|
||||
test_*
|
||||
*_test.py
|
||||
*_spec.rb
|
||||
|
||||
# Development files
|
||||
ai_docs/
|
||||
94
.env.example
Normal file
@@ -0,0 +1,94 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
# Licensed under the Apache License, Version 2.0 (see LICENSE)
|
||||
#
|
||||
# PotatoMesh Environment Configuration
|
||||
# Copy this file to .env and customize for your setup
|
||||
|
||||
# =============================================================================
|
||||
# REQUIRED SETTINGS
|
||||
# =============================================================================
|
||||
|
||||
# Public domain name for this PotatoMesh instance (required for webapp)
|
||||
# Provide a hostname (with optional port) that resolves to the web service.
|
||||
# Example: mesh.example.org or mesh.example.org:41447
|
||||
INSTANCE_DOMAIN="mesh.example.org"
|
||||
|
||||
# API authentication token (required for ingestor communication)
|
||||
# Generate a secure token: openssl rand -hex 32
|
||||
API_TOKEN="your-secure-api-token-here"
|
||||
|
||||
# Mesh radio connection target (required for ingestor)
|
||||
# Common serial paths:
|
||||
# - Linux: /dev/ttyACM0, /dev/ttyUSB0
|
||||
# - macOS: /dev/cu.usbserial-*
|
||||
# - Windows (WSL): /dev/ttyS*
|
||||
# You may also provide an IP:PORT pair (e.g. 192.168.1.20:4403) or a
|
||||
# Bluetooth address (e.g. ED:4D:9E:95:CF:60).
|
||||
CONNECTION="/dev/ttyACM0"
|
||||
|
||||
# Mesh protocol to use (meshtastic or meshcore)
|
||||
# Default: meshtastic
|
||||
PROTOCOL="meshtastic"
|
||||
|
||||
# =============================================================================
|
||||
# SITE CUSTOMIZATION
|
||||
# =============================================================================
|
||||
|
||||
# Your mesh network name
|
||||
SITE_NAME="My Meshtastic Network"
|
||||
|
||||
# Default Meshtastic channel
|
||||
CHANNEL="#LongFast"
|
||||
|
||||
# Default frequency for your region
|
||||
# Common frequencies: 868MHz (Europe), 915MHz (US), 433MHz (Worldwide)
|
||||
FREQUENCY="915MHz"
|
||||
|
||||
# Map center coordinates (latitude, longitude)
|
||||
# Berlin, Germany: 52.502889, 13.404194
|
||||
# Denver, Colorado: 39.7392, -104.9903
|
||||
# London, UK: 51.5074, -0.1278
|
||||
MAP_CENTER="38.761944,-27.090833"
|
||||
|
||||
# Maximum distance to show nodes (kilometers)
|
||||
MAX_DISTANCE=42
|
||||
|
||||
# =============================================================================
|
||||
# OPTIONAL INTEGRATIONS
|
||||
# =============================================================================
|
||||
|
||||
# Community chat link or Matrix room for your community (optional)
|
||||
# Matrix aliases (e.g. #meshtastic-berlin:matrix.org) will be linked via matrix.to automatically.
|
||||
CONTACT_LINK="#potatomesh:dod.ngo"
|
||||
|
||||
# Enable or disable PotatoMesh federation features (1=enabled, 0=disabled)
|
||||
FEDERATION=1
|
||||
|
||||
# Hide public mesh messages from unauthenticated visitors (1=hidden, 0=public)
|
||||
PRIVATE=0
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# ADVANCED SETTINGS
|
||||
# =============================================================================
|
||||
|
||||
# Debug mode (0=off, 1=on)
|
||||
DEBUG=0
|
||||
|
||||
# Energy saving mode — sleep between ingestion cycles (0=off, 1=on)
|
||||
ENERGY_SAVING=0
|
||||
|
||||
# Default map zoom override
|
||||
# MAP_ZOOM=15
|
||||
|
||||
# Docker image architecture (linux-amd64, linux-arm64, linux-armv7)
|
||||
POTATOMESH_IMAGE_ARCH="linux-amd64"
|
||||
|
||||
# Docker image tag (use "latest" for the newest release or pin to vX.Y)
|
||||
POTATOMESH_IMAGE_TAG="latest"
|
||||
|
||||
# Docker Compose networking profile
|
||||
# Leave unset for Linux hosts (default host networking).
|
||||
# Set to "bridge" on Docker Desktop (macOS/Windows) if host networking
|
||||
# is unavailable.
|
||||
# COMPOSE_PROFILES="bridge"
|
||||
41
.github/dependabot.yml
vendored
@@ -1,15 +1,40 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "ruby" # See documentation for possible values
|
||||
directory: "/web" # Location of package manifests
|
||||
- package-ecosystem: "ruby"
|
||||
directory: "/web"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "python" # See documentation for possible values
|
||||
directory: "/data" # Location of package manifests
|
||||
- package-ecosystem: "python"
|
||||
directory: "/data"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/matrix"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/web"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "pub"
|
||||
directory: "/app"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
15
.github/workflows/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# GitHub Actions Workflows
|
||||
|
||||
## Workflows
|
||||
|
||||
- **`docker.yml`** - Build and push Docker images to GHCR
|
||||
- **`codeql.yml`** - Security scanning
|
||||
- **`python.yml`** - Python ingestor pipeline
|
||||
- **`ruby.yml`** - Ruby Sinatra app testing
|
||||
- **`javascript.yml`** - Frontend test suite
|
||||
- **`mobile.yml`** - Flutter mobile tests with coverage reporting
|
||||
- **`release.yml`** - Tag-triggered Flutter release builds for Android and iOS
|
||||
|
||||
78
.github/workflows/codeql.yml
vendored
@@ -1,14 +1,17 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
# 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
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
# 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.
|
||||
|
||||
name: "CodeQL Advanced"
|
||||
|
||||
on:
|
||||
@@ -20,20 +23,10 @@ on:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
@@ -43,58 +36,21 @@ jobs:
|
||||
include:
|
||||
- language: python
|
||||
build-mode: none
|
||||
- language: rust
|
||||
build-mode: none
|
||||
- language: ruby
|
||||
build-mode: none
|
||||
- language: javascript-typescript
|
||||
build-mode: none
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
# - name: Setup runtime (example)
|
||||
# uses: actions/setup-example@v1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
uses: actions/checkout@v5
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
259
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Build and Push Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ 'v*' ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to publish (e.g., 1.0.0)'
|
||||
required: true
|
||||
default: '1.0.0'
|
||||
publish_all_variants:
|
||||
description: 'Publish all Docker image variants (latest tag)'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_PREFIX: l5yth/potato-mesh
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
if: (startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push') || github.event_name == 'workflow_dispatch'
|
||||
environment: production
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
service: [web, ingestor, matrix-bridge]
|
||||
architecture:
|
||||
- { name: linux-amd64, platform: linux/amd64, label: "Linux x86_64", os: linux, architecture: amd64 }
|
||||
- { name: linux-arm64, platform: linux/arm64, label: "Linux ARM64", os: linux, architecture: arm64 }
|
||||
- { name: linux-armv7, platform: linux/arm/v7, label: "Linux ARMv7", os: linux, architecture: arm }
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU emulation
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract version from tag or input
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
RAW_VERSION="${{ github.event.inputs.version }}"
|
||||
else
|
||||
RAW_VERSION=${GITHUB_REF#refs/tags/}
|
||||
fi
|
||||
|
||||
STRIPPED_VERSION=${RAW_VERSION#v}
|
||||
|
||||
echo "version=$STRIPPED_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version_with_v=v$STRIPPED_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "raw_version=$RAW_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Published version: $STRIPPED_VERSION"
|
||||
|
||||
- name: Determine tagging strategy
|
||||
id: tagging
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PUBLISH_ALL_VARIANTS: ${{ github.event.inputs.publish_all_variants || 'false' }}
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
|
||||
if echo "$VERSION" | grep -E -- '-(rc|beta|alpha|dev)'; then
|
||||
IS_PRERELEASE=true
|
||||
else
|
||||
IS_PRERELEASE=false
|
||||
fi
|
||||
|
||||
if [ "$IS_PRERELEASE" = "false" ] && { [ "$EVENT_NAME" = "push" ] || [ "$PUBLISH_ALL_VARIANTS" = "true" ]; }; then
|
||||
INCLUDE_LATEST=true
|
||||
else
|
||||
INCLUDE_LATEST=false
|
||||
fi
|
||||
|
||||
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
|
||||
echo "include_latest=$INCLUDE_LATEST" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push ${{ matrix.service }} for ${{ matrix.architecture.name }}
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.service == 'web' && './web/Dockerfile' || matrix.service == 'ingestor' && './data/Dockerfile' || './matrix/Dockerfile' }}
|
||||
target: ${{ matrix.service == 'matrix-bridge' && 'runtime' || 'production' }}
|
||||
platforms: ${{ matrix.architecture.platform }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}-${{ matrix.architecture.name }}:${{ steps.version.outputs.version }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.service }}-${{ matrix.architecture.name }}:${{ steps.version.outputs.version_with_v }}
|
||||
${{ steps.tagging.outputs.include_latest == 'true' && format('{0}/{1}-{2}-{3}:latest', env.REGISTRY, env.IMAGE_PREFIX, matrix.service, matrix.architecture.name) || '' }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.description=PotatoMesh ${{ matrix.service == 'web' && 'Web Application' || matrix.service == 'ingestor' && 'Python Ingestor' || 'Matrix Bridge' }} for ${{ matrix.architecture.label }}
|
||||
org.opencontainers.image.licenses=Apache-2.0
|
||||
org.opencontainers.image.version=${{ steps.version.outputs.version }}
|
||||
org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.title=PotatoMesh ${{ matrix.service == 'web' && 'Web' || matrix.service == 'ingestor' && 'Ingestor' || 'Matrix Bridge' }} (${{ matrix.architecture.label }})
|
||||
org.opencontainers.image.vendor=PotatoMesh
|
||||
org.opencontainers.image.architecture=${{ matrix.architecture.architecture }}
|
||||
org.opencontainers.image.os=${{ matrix.architecture.os }}
|
||||
cache-from: type=gha,scope=${{ matrix.service }}-${{ matrix.architecture.name }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.service }}-${{ matrix.architecture.name }}
|
||||
|
||||
test-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
if: startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract version from tag
|
||||
id: version
|
||||
run: |
|
||||
RAW_VERSION=${GITHUB_REF#refs/tags/}
|
||||
STRIPPED_VERSION=${RAW_VERSION#v}
|
||||
echo "version=$STRIPPED_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "version_with_v=v$STRIPPED_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Detect pre-release tag
|
||||
id: tagging
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
|
||||
if echo "$VERSION" | grep -E -- '-(rc|beta|alpha|dev)'; then
|
||||
INCLUDE_LATEST=false
|
||||
else
|
||||
INCLUDE_LATEST=true
|
||||
fi
|
||||
|
||||
echo "include_latest=$INCLUDE_LATEST" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Test web application (Linux AMD64)
|
||||
run: |
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-amd64:${{ steps.version.outputs.version }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-amd64:${{ steps.version.outputs.version_with_v }}
|
||||
docker run --rm -d --name web-test -p 41447:41447 \
|
||||
-e API_TOKEN=test-token \
|
||||
-e DEBUG=1 \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-amd64:${{ steps.version.outputs.version }}
|
||||
sleep 10
|
||||
curl -f http://localhost:41447/ || exit 1
|
||||
docker stop web-test
|
||||
|
||||
- name: Test ingestor (Linux AMD64)
|
||||
run: |
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-amd64:${{ steps.version.outputs.version }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-amd64:${{ steps.version.outputs.version_with_v }}
|
||||
docker run --rm --name ingestor-test \
|
||||
-e INSTANCE_DOMAIN=http://localhost:41447 \
|
||||
-e API_TOKEN=test-token \
|
||||
-e CONNECTION=mock \
|
||||
-e DEBUG=1 \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-amd64:${{ steps.version.outputs.version }} &
|
||||
sleep 5
|
||||
docker stop ingestor-test || true
|
||||
|
||||
publish-summary:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-and-push, test-images]
|
||||
if: always() && startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Extract version from tag
|
||||
id: version
|
||||
run: |
|
||||
VERSION=${GITHUB_REF#refs/tags/v}
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Determine tagging strategy
|
||||
id: tagging
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
|
||||
if echo "$VERSION" | grep -E -- '-(rc|beta|alpha|dev)'; then
|
||||
INCLUDE_LATEST=false
|
||||
else
|
||||
INCLUDE_LATEST=true
|
||||
fi
|
||||
|
||||
echo "include_latest=$INCLUDE_LATEST" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Publish release summary
|
||||
run: |
|
||||
echo "## 🚀 PotatoMesh Images Published to GHCR" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Published Images:**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Web images
|
||||
echo "### 🌐 Web Application" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ steps.tagging.outputs.include_latest }}" = "true" ]; then
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-amd64:latest\` - Linux x86_64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-arm64:latest\` - Linux ARM64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web-linux-armv7:latest\` - Linux ARMv7" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Ingestor images
|
||||
echo "### 📡 Ingestor Service" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ steps.tagging.outputs.include_latest }}" = "true" ]; then
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-amd64:latest\` - Linux x86_64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-arm64:latest\` - Linux ARM64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-ingestor-linux-armv7:latest\` - Linux ARMv7" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Matrix bridge images
|
||||
echo "### 🧩 Matrix Bridge" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ steps.tagging.outputs.include_latest }}" = "true" ]; then
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-matrix-bridge-linux-amd64:latest\` - Linux x86_64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-matrix-bridge-linux-arm64:latest\` - Linux ARM64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-matrix-bridge-linux-armv7:latest\` - Linux ARMv7" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
62
.github/workflows/javascript.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: JavaScript
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'web/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
frontend:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Node.js 22
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run JavaScript tests
|
||||
run: npm test
|
||||
- name: Upload coverage to Codecov
|
||||
if: always()
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: web/reports/javascript-coverage.json
|
||||
flags: frontend
|
||||
name: frontend
|
||||
fail_ci_if_error: false
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Upload test results to Codecov
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: web/reports/javascript-junit.xml
|
||||
flags: frontend
|
||||
72
.github/workflows/mobile.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Mobile
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'app/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
flutter:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./app
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
cache: true
|
||||
- name: Install dependencies
|
||||
run: flutter pub get
|
||||
- name: Run Flutter tests with coverage
|
||||
run: flutter test --coverage
|
||||
- name: Check formatting
|
||||
run: dart format --set-exit-if-changed .
|
||||
- name: Analyze Dart code
|
||||
run: flutter analyze
|
||||
- name: Build Android debug APK
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: flutter build apk --debug
|
||||
- name: Build iOS debug IPA
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: flutter build ipa --debug --no-codesign
|
||||
- name: Upload coverage to Codecov
|
||||
if: always()
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: coverage/lcov.info
|
||||
flags: flutter-mobile
|
||||
name: flutter-mobile
|
||||
fail_ci_if_error: false
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
35
.github/workflows/nix.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Nix
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
flake-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v30
|
||||
with:
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
- name: Run flake checks
|
||||
run: nix flake check
|
||||
66
.github/workflows/python.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Python
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'data/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
ingestor:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Python 3.13
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.13"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install black pytest pytest-cov meshtastic meshcore
|
||||
- name: Test with pytest and coverage
|
||||
run: |
|
||||
mkdir -p reports
|
||||
pytest --cov=data --cov-report=term --cov-report=xml:reports/python-coverage.xml --junitxml=reports/python-junit.xml
|
||||
- name: Upload coverage to Codecov
|
||||
if: always()
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: reports/python-coverage.xml
|
||||
flags: python-ingestor
|
||||
fail_ci_if_error: false
|
||||
name: python-ingestor
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Upload test results to Codecov
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: reports/python-junit.xml
|
||||
flags: python-ingestor
|
||||
- name: Lint with black
|
||||
run: |
|
||||
black --check ./
|
||||
144
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Mobile Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
android-release:
|
||||
name: Android Release
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./app
|
||||
env:
|
||||
TAG_NAME: ${{ github.ref_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Configure Android local.properties
|
||||
run: |
|
||||
cat > android/local.properties <<'EOF'
|
||||
sdk.dir=${ANDROID_SDK_ROOT}
|
||||
flutter.sdk=${FLUTTER_ROOT}
|
||||
EOF
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
cache: true
|
||||
cache-key: ${{ runner.os }}-flutter-${{ hashFiles('app/pubspec.lock') }}
|
||||
- name: Install dependencies
|
||||
run: flutter pub get
|
||||
- name: Build release APK
|
||||
run: flutter build apk --release
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
APK_DIR="build/app/outputs/flutter-apk"
|
||||
mv "${APK_DIR}/app-release.apk" "${APK_DIR}/potatomesh-reader-android-${TAG_NAME}.apk"
|
||||
(cd "${APK_DIR}" && sha256sum "potatomesh-reader-android-${TAG_NAME}.apk" > "potatomesh-reader-android-${TAG_NAME}.apk.sha256sum")
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: potatomesh-reader-android-${{ env.TAG_NAME }}
|
||||
path: |
|
||||
app/build/app/outputs/flutter-apk/potatomesh-reader-android-${{ env.TAG_NAME }}.apk
|
||||
app/build/app/outputs/flutter-apk/potatomesh-reader-android-${{ env.TAG_NAME }}.apk.sha256sum
|
||||
|
||||
ios-release:
|
||||
name: iOS Release
|
||||
runs-on: macos-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./app
|
||||
env:
|
||||
TAG_NAME: ${{ github.ref_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: stable
|
||||
cache: true
|
||||
cache-key: ${{ runner.os }}-flutter-${{ hashFiles('app/pubspec.lock') }}
|
||||
- name: Install dependencies
|
||||
run: flutter pub get
|
||||
- name: Build release IPA (no codesign)
|
||||
run: flutter build ipa --release --no-codesign
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
IPA_DIR="build/ios/ipa"
|
||||
IPA_FILE="$(ls "${IPA_DIR}"/*.ipa | head -n 1)"
|
||||
mv "${IPA_FILE}" "${IPA_DIR}/potatomesh-reader-ios-${TAG_NAME}.ipa"
|
||||
(cd "${IPA_DIR}" && shasum -a 256 "potatomesh-reader-ios-${TAG_NAME}.ipa" > "potatomesh-reader-ios-${TAG_NAME}.ipa.sha256sum")
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: potatomesh-reader-ios-${{ env.TAG_NAME }}
|
||||
path: |
|
||||
app/build/ios/ipa/potatomesh-reader-ios-${{ env.TAG_NAME }}.ipa
|
||||
app/build/ios/ipa/potatomesh-reader-ios-${{ env.TAG_NAME }}.ipa.sha256sum
|
||||
|
||||
publish-release:
|
||||
name: Publish Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- android-release
|
||||
- ios-release
|
||||
env:
|
||||
TAG_NAME: ${{ github.ref_name }}
|
||||
PUBLISH_RELEASE: "false"
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Check tag format
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "PUBLISH_RELEASE=true" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "Non point release tag (${TAG_NAME}); skipping publish."
|
||||
fi
|
||||
- name: Download Android artifacts
|
||||
if: env.PUBLISH_RELEASE == 'true'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: potatomesh-reader-android-${{ env.TAG_NAME }}
|
||||
path: artifacts/android
|
||||
- name: Download iOS artifacts
|
||||
if: env.PUBLISH_RELEASE == 'true'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: potatomesh-reader-ios-${{ env.TAG_NAME }}
|
||||
path: artifacts/ios
|
||||
- name: Attach assets to release
|
||||
if: env.PUBLISH_RELEASE == 'true'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
generate_release_notes: true
|
||||
files: |
|
||||
artifacts/android/potatomesh-reader-android-${{ env.TAG_NAME }}.apk
|
||||
artifacts/android/potatomesh-reader-android-${{ env.TAG_NAME }}.apk.sha256sum
|
||||
artifacts/ios/potatomesh-reader-ios-${{ env.TAG_NAME }}.ipa
|
||||
artifacts/ios/potatomesh-reader-ios-${{ env.TAG_NAME }}.ipa.sha256sum
|
||||
73
.github/workflows/ruby.yml
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Ruby
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'web/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sinatra:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./web
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby-version: ['3.4', '4.0']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version }}
|
||||
bundler-cache: true
|
||||
working-directory: ./web
|
||||
- name: Set up dependencies
|
||||
run: bundle install
|
||||
- name: Run tests
|
||||
run: |
|
||||
mkdir -p tmp/test-results
|
||||
bundle exec rspec \
|
||||
--require rspec_junit_formatter \
|
||||
--format progress \
|
||||
--format RspecJunitFormatter \
|
||||
--out tmp/test-results/rspec.xml
|
||||
- name: Upload test results to Codecov
|
||||
uses: codecov/test-results-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./web/tmp/test-results/rspec.xml
|
||||
flags: sinatra-${{ matrix.ruby-version }}
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
fail_ci_if_error: false
|
||||
flags: sinatra-${{ matrix.ruby-version }}
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Run rufo
|
||||
run: bundle exec rufo --check .
|
||||
78
.github/workflows/rust.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/**'
|
||||
- 'matrix/**'
|
||||
- 'tests/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: Cache Cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./matrix/target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml', '**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
- name: Show rustc version
|
||||
run: rustc --version
|
||||
- name: Install llvm-tools-preview component
|
||||
run: rustup component add llvm-tools-preview --toolchain stable
|
||||
- name: Install cargo-llvm-cov
|
||||
working-directory: ./matrix
|
||||
run: cargo install cargo-llvm-cov --locked
|
||||
- name: Check formatting
|
||||
working-directory: ./matrix
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Clippy lint
|
||||
working-directory: ./matrix
|
||||
run: cargo clippy --all-targets --all-features -- -D warnings
|
||||
- name: Build
|
||||
working-directory: ./matrix
|
||||
run: cargo build --all --all-features
|
||||
- name: Test
|
||||
working-directory: ./matrix
|
||||
run: cargo test --all --all-features --verbose
|
||||
- name: Run tests with coverage
|
||||
working-directory: ./matrix
|
||||
run: |
|
||||
cargo llvm-cov --all-features --workspace --lcov --output-path coverage.lcov
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./matrix/coverage.lcov
|
||||
flags: matrix-bridge
|
||||
name: matrix-bridge
|
||||
fail_ci_if_error: false
|
||||
25
.gitignore
vendored
@@ -11,7 +11,7 @@
|
||||
/tmp/
|
||||
|
||||
# Used by dotenv library to load environment variables.
|
||||
# .env
|
||||
.env
|
||||
|
||||
# Ignore Byebug command history file.
|
||||
.byebug_history
|
||||
@@ -57,3 +57,26 @@ Gemfile.lock
|
||||
|
||||
# Python cache directories
|
||||
__pycache__/
|
||||
.coverage
|
||||
coverage/
|
||||
coverage.xml
|
||||
htmlcov/
|
||||
reports/
|
||||
|
||||
# AI planning and documentation
|
||||
ai_docs/
|
||||
*.log
|
||||
|
||||
# Generated credentials for the instance
|
||||
web/.config
|
||||
|
||||
# JavaScript dependencies
|
||||
node_modules/
|
||||
web/node_modules/
|
||||
|
||||
# Operator-customised static pages (keep only the shipped default)
|
||||
web/pages/*.md
|
||||
|
||||
# Debug symbols
|
||||
ignored.txt
|
||||
ignored-*.txt
|
||||
|
||||
519
CHANGELOG.md
Normal file
@@ -0,0 +1,519 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# CHANGELOG
|
||||
|
||||
## v0.6.0
|
||||
|
||||
**Official multi-protocol release.** This version introduces first-class
|
||||
support for both Meshtastic and MeshCore mesh protocols via the new `PROTOCOL`
|
||||
environment variable. Key additions since v0.5.12:
|
||||
|
||||
* Feat: official MeshCore provider with BLE, TCP, and serial support
|
||||
* Feat: multi-protocol awareness across web frontend, ingestor, and mobile app
|
||||
* Enh: surface MeshCore role types and distinguish protocols in the UI
|
||||
|
||||
See v0.5.12 below for the full commit history of multi-protocol groundwork.
|
||||
|
||||
**Breaking changes — remove deprecated environment variable aliases:**
|
||||
|
||||
* Ingestor: remove `POTATOMESH_INSTANCE` env var — use `INSTANCE_DOMAIN` by @l5yth
|
||||
* Ingestor: remove `PROVIDER` env var — use `PROTOCOL` by @l5yth
|
||||
* Ingestor: remove `MESH_SERIAL` env var — use `CONNECTION` by @l5yth
|
||||
* Ingestor: remove `PORT` config alias — use `CONNECTION` by @l5yth
|
||||
* Docker: give `INSTANCE_DOMAIN` a default of `http://web:41447` in compose by @l5yth
|
||||
* Chore: bump version to 0.6.0 across web, matrix bridge, and mobile app by @l5yth
|
||||
|
||||
## v0.5.12
|
||||
|
||||
* Enh: surface meshcore role types (#680) by @l5yth in <https://github.com/l5yth/potato-mesh/pull/685>
|
||||
* Chore: refactor codebase before meshcore release by @l5yth in <https://github.com/l5yth/potato-mesh/pull/682>
|
||||
* [Meshcore] enh: short name should be 1st 4 hex digits of public key by @benallfree in <https://github.com/l5yth/potato-mesh/pull/679>
|
||||
* Chore: update xcode deps by @benallfree in <https://github.com/l5yth/potato-mesh/pull/674>
|
||||
* Chore: update mesh.sh to use requirements file by @benallfree in <https://github.com/l5yth/potato-mesh/pull/675>
|
||||
* Data/meshcore: fix ble and enable tcp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/669>
|
||||
* Data: handle store_forward and router_heartbeat portnum by @l5yth in <https://github.com/l5yth/potato-mesh/pull/667>
|
||||
* Feat: implement meshcore provider by @l5yth in <https://github.com/l5yth/potato-mesh/pull/663>
|
||||
* Ci: update dependabot and codecov settings by @l5yth in <https://github.com/l5yth/potato-mesh/pull/666>
|
||||
* Web: prepare release by @l5yth in <https://github.com/l5yth/potato-mesh/pull/665>
|
||||
* App: only query meshtastic provider by @l5yth in <https://github.com/l5yth/potato-mesh/pull/664>
|
||||
* Data: prepare ingestor for meshcore by @l5yth in <https://github.com/l5yth/potato-mesh/pull/658>
|
||||
* Web: fix css issues by @l5yth in <https://github.com/l5yth/potato-mesh/pull/659>
|
||||
* Web: prepare frontend for multi protocol by @l5yth in <https://github.com/l5yth/potato-mesh/pull/657>
|
||||
* Feat: split device and power-sensor telemetry charts (#643) by @l5yth in <https://github.com/l5yth/potato-mesh/pull/656>
|
||||
* Web: implement a 'protocol' field across systems by @l5yth in <https://github.com/l5yth/potato-mesh/pull/655>
|
||||
* Fix upsert clearing node coordinates bug by @l5yth in <https://github.com/l5yth/potato-mesh/pull/654>
|
||||
* Data: resolve circular dependency of deamon.py by @l5yth in <https://github.com/l5yth/potato-mesh/pull/653>
|
||||
* Proposal: mesh provider pattern refactor by @benallfree in <https://github.com/l5yth/potato-mesh/pull/651>
|
||||
* Build(deps): bump rustls-webpki from 0.103.8 to 0.103.10 in /matrix by @dependabot[bot]< in https://github.com/l5yth/potato-mesh/pull/649>
|
||||
* Build(deps): bump quinn-proto from 0.11.13 to 0.11.14 in /matrix by @dependabot[bot]< in https://github.com/l5yth/potato-mesh/pull/646>
|
||||
|
||||
## v0.5.11
|
||||
|
||||
* Chore: bump version to 0.5.11 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/645>
|
||||
* Web: limit horizontal size of dropdown by @l5yth in <https://github.com/l5yth/potato-mesh/pull/644>
|
||||
|
||||
## v0.5.10
|
||||
|
||||
* Web: expose node stats in distinct api by @l5yth in <https://github.com/l5yth/potato-mesh/pull/641>
|
||||
* Web: do merge channels by name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/640>
|
||||
* Web: do not merge channels by ID in frontend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/637>
|
||||
* Web: do not touch neighbor last seen on neighbor info by @l5yth in <https://github.com/l5yth/potato-mesh/pull/636>
|
||||
* Ingestor: report self id per packet by @l5yth in <https://github.com/l5yth/potato-mesh/pull/635>
|
||||
* Ci: fix docker compose and docs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/634>
|
||||
* Web: supress encrypted text messages in frontend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/633>
|
||||
* Federation: ensure requests timeout properly and can be terminated by @l5yth in <https://github.com/l5yth/potato-mesh/pull/631>
|
||||
* Build(deps): bump bytes from 1.11.0 to 1.11.1 in /matrix by @dependabot[bot]< in https://github.com/l5yth/potato-mesh/pull/627>
|
||||
* Matrix: config loading now merges optional TOML with CLI/env/secret inputs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/617>
|
||||
* Matrix: logs only non-sensitive config fields by @l5yth in <https://github.com/l5yth/potato-mesh/pull/616>
|
||||
* Web: decrypted takes precedence by @l5yth in <https://github.com/l5yth/potato-mesh/pull/614>
|
||||
* Add Apache 2.0 license headers to missing sources by @l5yth in <https://github.com/l5yth/potato-mesh/pull/615>
|
||||
* Web: decrypt PSK-1 unencrypted messages on arrival by @l5yth in <https://github.com/l5yth/potato-mesh/pull/611>
|
||||
* Web: daemonize federation worker pool to avoid deadlocks on stuck announcments by @l5yth in <https://github.com/l5yth/potato-mesh/pull/610>
|
||||
* Web: add announcement banner by @l5yth in <https://github.com/l5yth/potato-mesh/pull/609>
|
||||
* L5Y chore version 0510 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/608>
|
||||
|
||||
## v0.5.9
|
||||
|
||||
* Matrix: listen for synapse on port 41448 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/607>
|
||||
* Web: collapse federation map ledgend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/604>
|
||||
* Web: fix stale node queries by @l5yth in <https://github.com/l5yth/potato-mesh/pull/603>
|
||||
* Matrix: move short name to display name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/602>
|
||||
* Ci: update ruby to 4 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/601>
|
||||
* Web: display traces of last 28 days if available by @l5yth in <https://github.com/l5yth/potato-mesh/pull/599>
|
||||
* Web: establish menu structure by @l5yth in <https://github.com/l5yth/potato-mesh/pull/597>
|
||||
* Matrix: fixed the text-message checkpoint regression by @l5yth in <https://github.com/l5yth/potato-mesh/pull/595>
|
||||
* Matrix: cache seen messages by rx_time not id by @l5yth in <https://github.com/l5yth/potato-mesh/pull/594>
|
||||
* Web: hide the default '0' tab when not active by @l5yth in <https://github.com/l5yth/potato-mesh/pull/593>
|
||||
* Matrix: fix empty bridge state json by @l5yth in <https://github.com/l5yth/potato-mesh/pull/592>
|
||||
* Web: allow certain charts to overflow upper bounds by @l5yth in <https://github.com/l5yth/potato-mesh/pull/585>
|
||||
* Ingestor: support ROUTING_APP messages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/584>
|
||||
* Ci: run nix flake check on ci by @l5yth in <https://github.com/l5yth/potato-mesh/pull/583>
|
||||
* Web: hide legend by default by @l5yth in <https://github.com/l5yth/potato-mesh/pull/582>
|
||||
* Nix flake by @benjajaja in <https://github.com/l5yth/potato-mesh/pull/577>
|
||||
* Support BLE UUID format for macOS Bluetooth devices by @apo-mak in <https://github.com/l5yth/potato-mesh/pull/575>
|
||||
* Web: add mesh.qrp.ro as seed node by @l5yth in <https://github.com/l5yth/potato-mesh/pull/573>
|
||||
* Web: ensure unknown nodes for messages and traces by @l5yth in <https://github.com/l5yth/potato-mesh/pull/572>
|
||||
* Chore: bump version to 0.5.9 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/569>
|
||||
|
||||
## v0.5.8
|
||||
|
||||
* Web: add secondary seed node jmrp.io by @l5yth in <https://github.com/l5yth/potato-mesh/pull/568>
|
||||
* Data: implement whitelist for ingestor by @l5yth in <https://github.com/l5yth/potato-mesh/pull/567>
|
||||
* Web: add ?since= parameter to all apis by @l5yth in <https://github.com/l5yth/potato-mesh/pull/566>
|
||||
* Matrix: fix docker build by @l5yth in <https://github.com/l5yth/potato-mesh/pull/565>
|
||||
* Matrix: fix docker build by @l5yth in <https://github.com/l5yth/potato-mesh/pull/564>
|
||||
* Web: fix federation signature validation and create fallback by @l5yth in <https://github.com/l5yth/potato-mesh/pull/563>
|
||||
* Chore: update readme by @l5yth in <https://github.com/l5yth/potato-mesh/pull/561>
|
||||
* Matrix: add docker file for bridge by @l5yth in <https://github.com/l5yth/potato-mesh/pull/556>
|
||||
* Matrix: add health checks to startup by @l5yth in <https://github.com/l5yth/potato-mesh/pull/555>
|
||||
* Matrix: omit the api part in base url by @l5yth in <https://github.com/l5yth/potato-mesh/pull/554>
|
||||
* App: add utility coverage tests for main.dart by @l5yth in <https://github.com/l5yth/potato-mesh/pull/552>
|
||||
* Data: add thorough daemon unit tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/553>
|
||||
* Chore: bump version to 0.5.8 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/551>
|
||||
|
||||
## v0.5.7
|
||||
|
||||
* Data: track ingestors heartbeat by @l5yth in <https://github.com/l5yth/potato-mesh/pull/549>
|
||||
* Harden instance selector navigation URLs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/550>
|
||||
* Data: hide channels that have been flag for ignoring by @l5yth in <https://github.com/l5yth/potato-mesh/pull/548>
|
||||
* Web: fix limit when counting remote nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/547>
|
||||
* Web: improve instances map and table view by @l5yth in <https://github.com/l5yth/potato-mesh/pull/546>
|
||||
* Web: fix traces submission with optional fields on udp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/545>
|
||||
* Chore: bump version to 0.5.7 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/542>
|
||||
* Handle zero telemetry aggregates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/538>
|
||||
* Web: fix telemetry api to return current in amperes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/541>
|
||||
* Web: fix traces rendering by @l5yth in <https://github.com/l5yth/potato-mesh/pull/535>
|
||||
* Normalize numeric node roles to canonical labels by @l5yth in <https://github.com/l5yth/potato-mesh/pull/539>
|
||||
* Use INSTANCE_DOMAIN env for ingestor by @l5yth in <https://github.com/l5yth/potato-mesh/pull/536>
|
||||
* Web: further refine the federation page by @l5yth in <https://github.com/l5yth/potato-mesh/pull/534>
|
||||
* Add Federation Map by @apo-mak in <https://github.com/l5yth/potato-mesh/pull/532>
|
||||
* Add contact link to the instance data by @apo-mak in <https://github.com/l5yth/potato-mesh/pull/533>
|
||||
* Matrix: create potato-matrix-bridge by @l5yth in <https://github.com/l5yth/potato-mesh/pull/528>
|
||||
|
||||
## v0.5.6
|
||||
|
||||
* Web: display sats in view by @l5yth in <https://github.com/l5yth/potato-mesh/pull/523>
|
||||
* Web: display air quality in separate chart by @l5yth in <https://github.com/l5yth/potato-mesh/pull/521>
|
||||
* Ci: Add macOS and Ubuntu builds to Flutter workflow by @l5yth in <https://github.com/l5yth/potato-mesh/pull/519>
|
||||
* Web: add current to charts by @l5yth in <https://github.com/l5yth/potato-mesh/pull/520>
|
||||
* App: fix notification icon by @l5yth in <https://github.com/l5yth/potato-mesh/pull/518>
|
||||
* Spec: update test fixtures by @l5yth in <https://github.com/l5yth/potato-mesh/pull/517>
|
||||
* App: generate proper icons by @l5yth in <https://github.com/l5yth/potato-mesh/pull/516>
|
||||
* Web: fix favicon by @l5yth in <https://github.com/l5yth/potato-mesh/pull/515>
|
||||
* Web: add ?since= parameter to api/messages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/512>
|
||||
* App: implement notifications by @l5yth in <https://github.com/l5yth/potato-mesh/pull/511>
|
||||
* App: add theme selector by @l5yth in <https://github.com/l5yth/potato-mesh/pull/507>
|
||||
* App: further harden refresh logic and prefer local first by @l5yth in <https://github.com/l5yth/potato-mesh/pull/506>
|
||||
* Ci: fix app artifacts for tags by @l5yth in <https://github.com/l5yth/potato-mesh/pull/504>
|
||||
* Ci: build app artifacts for tags by @l5yth in <https://github.com/l5yth/potato-mesh/pull/503>
|
||||
* App: add persistance by @l5yth in <https://github.com/l5yth/potato-mesh/pull/501>
|
||||
* App: instance and chat mvp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/498>
|
||||
* App: add instance selector to settings by @l5yth in <https://github.com/l5yth/potato-mesh/pull/497>
|
||||
* App: add scaffholding gitignore by @l5yth in <https://github.com/l5yth/potato-mesh/pull/496>
|
||||
* Handle reaction app packets without reply id by @l5yth in <https://github.com/l5yth/potato-mesh/pull/495>
|
||||
* Render reaction multiplier counts by @l5yth in <https://github.com/l5yth/potato-mesh/pull/494>
|
||||
* Add comprehensive tests for Flutter reader by @l5yth in <https://github.com/l5yth/potato-mesh/pull/491>
|
||||
* Map numeric role ids to canonical Meshtastic roles by @l5yth in <https://github.com/l5yth/potato-mesh/pull/489>
|
||||
* Update node detail hydration for traces by @l5yth in <https://github.com/l5yth/potato-mesh/pull/490>
|
||||
* Add mobile Flutter CI workflow by @l5yth in <https://github.com/l5yth/potato-mesh/pull/488>
|
||||
* Align OCI labels in docker workflow by @l5yth in <https://github.com/l5yth/potato-mesh/pull/487>
|
||||
* Add Meshtastic reader Flutter app by @l5yth in <https://github.com/l5yth/potato-mesh/pull/483>
|
||||
* Handle pre-release Docker tagging by @l5yth in <https://github.com/l5yth/potato-mesh/pull/486>
|
||||
* Web: remove range from charts labels by @l5yth in <https://github.com/l5yth/potato-mesh/pull/485>
|
||||
* Floor override frequencies to MHz integers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/476>
|
||||
* Prevent message ids from being treated as node identifiers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/475>
|
||||
* Fix 1 after emojis in reply. by @Alexkurd in <https://github.com/l5yth/potato-mesh/pull/464>
|
||||
* Add frequency and preset to node table by @l5yth in <https://github.com/l5yth/potato-mesh/pull/472>
|
||||
* Subscribe to traceroute app pubsub topic by @l5yth in <https://github.com/l5yth/potato-mesh/pull/471>
|
||||
* Aggregate telemetry over the last 7 days by @l5yth in <https://github.com/l5yth/potato-mesh/pull/470>
|
||||
* Address missing id field ingestor bug by @l5yth in <https://github.com/l5yth/potato-mesh/pull/469>
|
||||
* Merge secondary channels by name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/468>
|
||||
* Rate limit host device telemetry by @l5yth in <https://github.com/l5yth/potato-mesh/pull/467>
|
||||
* Add traceroutes to frontend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/466>
|
||||
* Feat: implement traceroute app packet handling across the stack by @l5yth in <https://github.com/l5yth/potato-mesh/pull/463>
|
||||
* Bump version and update changelog by @l5yth in <https://github.com/l5yth/potato-mesh/pull/462>
|
||||
|
||||
## v0.5.5
|
||||
|
||||
* Added comprehensive helper unit tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/457>
|
||||
* Added reaction-aware handling by @l5yth in <https://github.com/l5yth/potato-mesh/pull/455>
|
||||
* Env: add map zoom by @l5yth in <https://github.com/l5yth/potato-mesh/pull/454>
|
||||
* Charts: render aggregated telemetry charts for all nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/453>
|
||||
* Nodes: render charts detail pages as overlay by @l5yth in <https://github.com/l5yth/potato-mesh/pull/452>
|
||||
* Fix telemetry parsing for charts by @l5yth in <https://github.com/l5yth/potato-mesh/pull/451>
|
||||
* Nodes: improve charts on detail pages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/450>
|
||||
* Nodes: add charts to detail pages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/449>
|
||||
* Aggregate frontend snapshots across views by @l5yth in <https://github.com/l5yth/potato-mesh/pull/447>
|
||||
* Remove added 1 if reply with emoji by @Alexkurd in <https://github.com/l5yth/potato-mesh/pull/443>
|
||||
* Refine node detail view layout by @l5yth in <https://github.com/l5yth/potato-mesh/pull/442>
|
||||
* Enable map centering from node table coordinates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/439>
|
||||
* Add node detail route and page by @l5yth in <https://github.com/l5yth/potato-mesh/pull/441>
|
||||
* Ensure Meshtastic nodeinfo patch runs before importing interfaces by @l5yth in <https://github.com/l5yth/potato-mesh/pull/440>
|
||||
* Filter zero-valued fields from API responses by @l5yth in <https://github.com/l5yth/potato-mesh/pull/438>
|
||||
* Add debug payload tracing and ignored packet logging by @l5yth in <https://github.com/l5yth/potato-mesh/pull/437>
|
||||
* Tighten map auto-fit behaviour by @l5yth in <https://github.com/l5yth/potato-mesh/pull/435>
|
||||
* Fetch encrypted chat log entries for log tab by @l5yth in <https://github.com/l5yth/potato-mesh/pull/434>
|
||||
* Add encrypted filter to messages API by @l5yth in <https://github.com/l5yth/potato-mesh/pull/432>
|
||||
* Guard NodeInfo handler against missing IDs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/431>
|
||||
* Add standalone full-screen map, chat, and nodes views by @l5yth in <https://github.com/l5yth/potato-mesh/pull/429>
|
||||
* Ensure chat history fetches full message limit by @l5yth in <https://github.com/l5yth/potato-mesh/pull/428>
|
||||
* Fix ingestion of nodeinfo packets missing ids (#426) by @l5yth in <https://github.com/l5yth/potato-mesh/pull/427>
|
||||
* Chore: update license headers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/424>
|
||||
* Chore: bump version to 0.5.5 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/423>
|
||||
|
||||
## v0.5.4
|
||||
|
||||
* Handle naming when primary channel has a name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/422>
|
||||
* Handle edge case when primary channel has a name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/421>
|
||||
* Add preset mode to logs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/420>
|
||||
* Parallelize federation tasks with worker pool by @l5yth in <https://github.com/l5yth/potato-mesh/pull/419>
|
||||
* Allow filtering chat and logs by node name by @l5yth in <https://github.com/l5yth/potato-mesh/pull/417>
|
||||
* Gem: Add erb as dependency removed from std by @l5yth in <https://github.com/l5yth/potato-mesh/pull/416>
|
||||
* Implement support for replies and reactions app by @l5yth in <https://github.com/l5yth/potato-mesh/pull/411>
|
||||
* Ingestor: Ignore direct messages on default channel by @l5yth in <https://github.com/l5yth/potato-mesh/pull/414>
|
||||
* Agents: Add instructions by @l5yth in <https://github.com/l5yth/potato-mesh/pull/410>
|
||||
* Display encrypted messages in frontend log window by @l5yth in <https://github.com/l5yth/potato-mesh/pull/409>
|
||||
* Add chat log entries for telemetry, position, and neighbor events by @l5yth in <https://github.com/l5yth/potato-mesh/pull/408>
|
||||
* Handle missing instance domain outside production by @l5yth in <https://github.com/l5yth/potato-mesh/pull/405>
|
||||
* Add tabbed chat panel with channel grouping by @l5yth in <https://github.com/l5yth/potato-mesh/pull/404>
|
||||
* Normalize numeric client roles using Meshtastic CLI enums by @l5yth in <https://github.com/l5yth/potato-mesh/pull/402>
|
||||
* Ensure Docker images publish versioned tags by @l5yth in <https://github.com/l5yth/potato-mesh/pull/403>
|
||||
* Document environment configuration variables by @l5yth in <https://github.com/l5yth/potato-mesh/pull/400>
|
||||
* Document federation refresh cadence by @l5yth in <https://github.com/l5yth/potato-mesh/pull/401>
|
||||
* Add Prometheus monitoring documentation by @l5yth in <https://github.com/l5yth/potato-mesh/pull/399>
|
||||
* Config: Read PROM_REPORT_IDS from environment by @nicjansma in <https://github.com/l5yth/potato-mesh/pull/398>
|
||||
* Feat: Mesh-Ingestor: Ability to provide already-existing interface instance by @KenADev in <https://github.com/l5yth/potato-mesh/pull/395>
|
||||
* Fix: Mesh-Ingestor: Fix error for non-existing datetime.UTC reference by @KenADev in <https://github.com/l5yth/potato-mesh/pull/396>
|
||||
* Chore: bump version to 0.5.4 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/388>
|
||||
|
||||
## v0.5.3
|
||||
|
||||
* Add telemetry formatting utilities and extend node overlay by @l5yth in <https://github.com/l5yth/potato-mesh/pull/387>
|
||||
* Prune blank values from API responses by @l5yth in <https://github.com/l5yth/potato-mesh/pull/386>
|
||||
* Add full support to telemetry schema and API by @l5yth in <https://github.com/l5yth/potato-mesh/pull/385>
|
||||
* Respect PORT environment override by @l5yth in <https://github.com/l5yth/potato-mesh/pull/384>
|
||||
* Add instance selector dropdown for federation deployments by @l5yth in <https://github.com/l5yth/potato-mesh/pull/382>
|
||||
* Harden federation announcements by @l5yth in <https://github.com/l5yth/potato-mesh/pull/381>
|
||||
* Ensure private mode disables federation by @l5yth in <https://github.com/l5yth/potato-mesh/pull/380>
|
||||
* Ensure private mode disables chat messaging by @l5yth in <https://github.com/l5yth/potato-mesh/pull/378>
|
||||
* Disable federation features when FEDERATION=0 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/379>
|
||||
* Expose PRIVATE environment configuration across tooling by @l5yth in <https://github.com/l5yth/potato-mesh/pull/377>
|
||||
* Fix frontend coverage export for Codecov by @l5yth in <https://github.com/l5yth/potato-mesh/pull/376>
|
||||
* Restrict /api/instances results to recent records by @l5yth in <https://github.com/l5yth/potato-mesh/pull/374>
|
||||
* Expose FEDERATION environment option across tooling by @l5yth in <https://github.com/l5yth/potato-mesh/pull/375>
|
||||
* Chore: bump version to 0.5.3 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/372>
|
||||
|
||||
## v0.5.2
|
||||
|
||||
* Align theme and info controls by @l5yth in <https://github.com/l5yth/potato-mesh/pull/371>
|
||||
* Fixes POST request 403 errors on instances behind Cloudflare proxy by @varna9000 in <https://github.com/l5yth/potato-mesh/pull/368>
|
||||
* Delay initial federation announcements by @l5yth in <https://github.com/l5yth/potato-mesh/pull/366>
|
||||
* Ensure well-known document stays in sync on startup by @l5yth in <https://github.com/l5yth/potato-mesh/pull/365>
|
||||
* Guard federation DNS resolution against restricted networks by @l5yth in <https://github.com/l5yth/potato-mesh/pull/362>
|
||||
* Add federation ingestion limits and tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/364>
|
||||
* Prefer reported primary channel names by @l5yth in <https://github.com/l5yth/potato-mesh/pull/363>
|
||||
* Decouple message API node hydration by @l5yth in <https://github.com/l5yth/potato-mesh/pull/360>
|
||||
* Fix ingestor reconnection detection by @l5yth in <https://github.com/l5yth/potato-mesh/pull/361>
|
||||
* Harden instance domain validation by @l5yth in <https://github.com/l5yth/potato-mesh/pull/359>
|
||||
* Ensure INSTANCE_DOMAIN propagates to containers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/358>
|
||||
* Chore: bump version to 0.5.2 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/356>
|
||||
* Gracefully retry federation announcements over HTTP by @l5yth in <https://github.com/l5yth/potato-mesh/pull/355>
|
||||
|
||||
## v0.5.1
|
||||
|
||||
* Recursively ingest federated instances by @l5yth in <https://github.com/l5yth/potato-mesh/pull/353>
|
||||
* Remove federation timeout environment overrides by @l5yth in <https://github.com/l5yth/potato-mesh/pull/352>
|
||||
* Close unrelated short info overlays when opening short info by @l5yth in <https://github.com/l5yth/potato-mesh/pull/351>
|
||||
* Improve federation instance error diagnostics by @l5yth in <https://github.com/l5yth/potato-mesh/pull/350>
|
||||
* Harden federation domain validation and tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/347>
|
||||
* Handle malformed instance records gracefully by @l5yth in <https://github.com/l5yth/potato-mesh/pull/348>
|
||||
* Fix ingestor device mounting for non-serial connections by @l5yth in <https://github.com/l5yth/potato-mesh/pull/346>
|
||||
* Ensure Docker deployments persist keyfile and well-known assets by @l5yth in <https://github.com/l5yth/potato-mesh/pull/345>
|
||||
* Add modem preset display to node overlay by @l5yth in <https://github.com/l5yth/potato-mesh/pull/340>
|
||||
* Display message frequency and channel in chat log by @l5yth in <https://github.com/l5yth/potato-mesh/pull/339>
|
||||
* Bump fallback version string to v0.5.1 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/338>
|
||||
* Docs: update changelog for 0.5.0 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/337>
|
||||
* Fix ingestor docker import path by @l5yth in <https://github.com/l5yth/potato-mesh/pull/336>
|
||||
|
||||
## v0.5.0
|
||||
|
||||
* Ensure node overlays appear above fullscreen map by @l5yth in <https://github.com/l5yth/potato-mesh/pull/333>
|
||||
* Adjust node table columns responsively by @l5yth in <https://github.com/l5yth/potato-mesh/pull/332>
|
||||
* Add LoRa metadata fields to nodes and messages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/331>
|
||||
* Add channel metadata capture for message tagging by @l5yth in <https://github.com/l5yth/potato-mesh/pull/329>
|
||||
* Capture radio metadata for ingestor payloads by @l5yth in <https://github.com/l5yth/potato-mesh/pull/327>
|
||||
* Fix FrozenError when filtering node query results by @l5yth in <https://github.com/l5yth/potato-mesh/pull/324>
|
||||
* Ensure frontend reports git-aware version strings by @l5yth in <https://github.com/l5yth/potato-mesh/pull/321>
|
||||
* Ensure web Docker image ships application sources by @l5yth in <https://github.com/l5yth/potato-mesh/pull/322>
|
||||
* Refine stacked short info overlays on the map by @l5yth in <https://github.com/l5yth/potato-mesh/pull/319>
|
||||
* Refine environment configuration defaults by @l5yth in <https://github.com/l5yth/potato-mesh/pull/318>
|
||||
* Fix legacy configuration migration to XDG directories by @l5yth in <https://github.com/l5yth/potato-mesh/pull/317>
|
||||
* Adopt XDG base directories for app data and config by @l5yth in <https://github.com/l5yth/potato-mesh/pull/316>
|
||||
* Refactor: streamline ingestor environment variables by @l5yth in <https://github.com/l5yth/potato-mesh/pull/314>
|
||||
* Adjust map auto-fit padding and default zoom by @l5yth in <https://github.com/l5yth/potato-mesh/pull/315>
|
||||
* Ensure APIs filter stale data and refresh node details from latest sources by @l5yth in <https://github.com/l5yth/potato-mesh/pull/312>
|
||||
* Improve offline tile fallback initialization by @l5yth in <https://github.com/l5yth/potato-mesh/pull/307>
|
||||
* Add fallback for offline tile rendering errors by @l5yth in <https://github.com/l5yth/potato-mesh/pull/306>
|
||||
* Fix map auto-fit handling and add controller by @l5yth in <https://github.com/l5yth/potato-mesh/pull/311>
|
||||
* Fix map initialization bounds and add coverage by @l5yth in <https://github.com/l5yth/potato-mesh/pull/305>
|
||||
* Increase coverage for configuration and sanitizer helpers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/303>
|
||||
* Add comprehensive theme and background front-end tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/302>
|
||||
* Document sanitization and helper modules by @l5yth in <https://github.com/l5yth/potato-mesh/pull/301>
|
||||
* Add in-repo Meshtastic protobuf stubs for tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/300>
|
||||
* Handle CRL lookup failures during federation TLS by @l5yth in <https://github.com/l5yth/potato-mesh/pull/299>
|
||||
* Ensure JavaScript workflow runs frontend tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/298>
|
||||
* Unify structured logging across application and ingestor by @l5yth in <https://github.com/l5yth/potato-mesh/pull/296>
|
||||
* Add Apache license headers to missing sources by @l5yth in <https://github.com/l5yth/potato-mesh/pull/297>
|
||||
* Update workflows for ingestor, sinatra, and frontend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/295>
|
||||
* Fix IPv6 instance domain canonicalization by @l5yth in <https://github.com/l5yth/potato-mesh/pull/294>
|
||||
* Handle federation HTTPS CRL verification failures by @l5yth in <https://github.com/l5yth/potato-mesh/pull/293>
|
||||
* Adjust federation announcement interval to eight hours by @l5yth in <https://github.com/l5yth/potato-mesh/pull/292>
|
||||
* Restore modular app functionality by @l5yth in <https://github.com/l5yth/potato-mesh/pull/291>
|
||||
* Refactor config and metadata helpers into PotatoMesh modules by @l5yth in <https://github.com/l5yth/potato-mesh/pull/290>
|
||||
* Update default site configuration defaults by @l5yth in <https://github.com/l5yth/potato-mesh/pull/288>
|
||||
* Add regression test for queue drain concurrency by @l5yth in <https://github.com/l5yth/potato-mesh/pull/287>
|
||||
* Ensure Docker config directories are created for non-root user by @l5yth in <https://github.com/l5yth/potato-mesh/pull/286>
|
||||
* Clarify numeric address requirement for network target parsing by @l5yth in <https://github.com/l5yth/potato-mesh/pull/285>
|
||||
* Ensure mesh ingestor queue resets active flag when idle by @l5yth in <https://github.com/l5yth/potato-mesh/pull/284>
|
||||
* Clarify BLE connection description in README by @l5yth in <https://github.com/l5yth/potato-mesh/pull/283>
|
||||
* Configure web container for production mode by @l5yth in <https://github.com/l5yth/potato-mesh/pull/282>
|
||||
* Normalize INSTANCE_DOMAIN configuration to require hostnames by @l5yth in <https://github.com/l5yth/potato-mesh/pull/280>
|
||||
* Avoid blocking startup on federation announcements by @l5yth in <https://github.com/l5yth/potato-mesh/pull/281>
|
||||
* Fix production Docker builds for web and ingestor images by @l5yth in <https://github.com/l5yth/potato-mesh/pull/279>
|
||||
* Improve instance domain detection logic by @l5yth in <https://github.com/l5yth/potato-mesh/pull/278>
|
||||
* Implement federation announcements and instances API by @l5yth in <https://github.com/l5yth/potato-mesh/pull/277>
|
||||
* Fix federation signature handling and IP guard by @l5yth in <https://github.com/l5yth/potato-mesh/pull/276>
|
||||
* Add persistent federation metadata endpoint by @l5yth in <https://github.com/l5yth/potato-mesh/pull/274>
|
||||
* Add configurable instance domain with reverse DNS fallback by @l5yth in <https://github.com/l5yth/potato-mesh/pull/272>
|
||||
* Document production deployment configuration by @l5yth in <https://github.com/l5yth/potato-mesh/pull/273>
|
||||
* Add targeted API endpoints and expose version metadata by @l5yth in <https://github.com/l5yth/potato-mesh/pull/271>
|
||||
* Prometheus metrics updates on startup and for position/telemetry by @nicjansma in <https://github.com/l5yth/potato-mesh/pull/270>
|
||||
* Add hourly reconnect handling for inactive mesh interface by @l5yth in <https://github.com/l5yth/potato-mesh/pull/267>
|
||||
* Dockerfile fixes by @nicjansma in <https://github.com/l5yth/potato-mesh/pull/268>
|
||||
* Added prometheus /metrics endpoint by @nicjansma in <https://github.com/l5yth/potato-mesh/pull/262>
|
||||
* Add fullscreen toggle to map view by @l5yth in <https://github.com/l5yth/potato-mesh/pull/263>
|
||||
* Relocate JS coverage export script into web directory by @l5yth in <https://github.com/l5yth/potato-mesh/pull/266>
|
||||
* V0.4.0 version string in web UI by @nicjansma in <https://github.com/l5yth/potato-mesh/pull/265>
|
||||
* Add energy saving cycle to ingestor daemon by @l5yth in <https://github.com/l5yth/potato-mesh/pull/256>
|
||||
* Chore: restore apache headers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/260>
|
||||
* Docs: add matrix to readme by @l5yth in <https://github.com/l5yth/potato-mesh/pull/259>
|
||||
* Force dark theme default based on sanitized cookie by @l5yth in <https://github.com/l5yth/potato-mesh/pull/252>
|
||||
* Document mesh ingestor modules with PDoc-style docstrings by @l5yth in <https://github.com/l5yth/potato-mesh/pull/255>
|
||||
* Handle missing node IDs in Meshtastic nodeinfo packets by @l5yth in <https://github.com/l5yth/potato-mesh/pull/251>
|
||||
* Document Ruby helper methods with RDoc comments by @l5yth in <https://github.com/l5yth/potato-mesh/pull/254>
|
||||
* Add JSDoc documentation across client scripts by @l5yth in <https://github.com/l5yth/potato-mesh/pull/253>
|
||||
* Fix mesh ingestor telemetry and neighbor handling by @l5yth in <https://github.com/l5yth/potato-mesh/pull/249>
|
||||
* Refactor front-end assets into external modules by @l5yth in <https://github.com/l5yth/potato-mesh/pull/245>
|
||||
* Add tests for helper utilities and asset routes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/243>
|
||||
* Docs: add ingestor inline docstrings by @l5yth in <https://github.com/l5yth/potato-mesh/pull/244>
|
||||
* Add comprehensive coverage tests for mesh ingestor by @l5yth in <https://github.com/l5yth/potato-mesh/pull/241>
|
||||
* Add inline documentation to config helpers and frontend scripts by @l5yth in <https://github.com/l5yth/potato-mesh/pull/240>
|
||||
* Update changelog by @l5yth in <https://github.com/l5yth/potato-mesh/pull/238>
|
||||
|
||||
## v0.4.0
|
||||
|
||||
* Reformat neighbor overlay layout by @l5yth in <https://github.com/l5yth/potato-mesh/pull/237>
|
||||
* Add legend toggle for neighbor lines by @l5yth in <https://github.com/l5yth/potato-mesh/pull/236>
|
||||
* Hide Air Util Tx column on mobile by @l5yth in <https://github.com/l5yth/potato-mesh/pull/235>
|
||||
* Add overlay for clickable neighbor links on map by @l5yth in <https://github.com/l5yth/potato-mesh/pull/234>
|
||||
* Hide humidity and pressure columns on mobile by @l5yth in <https://github.com/l5yth/potato-mesh/pull/232>
|
||||
* Remove last position timestamp from map info overlay by @l5yth in <https://github.com/l5yth/potato-mesh/pull/233>
|
||||
* Improve live node positions and expose precision metadata by @l5yth in <https://github.com/l5yth/potato-mesh/pull/231>
|
||||
* Show neighbor short names in info overlays by @l5yth in <https://github.com/l5yth/potato-mesh/pull/228>
|
||||
* Add telemetry environment metrics to node UI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/227>
|
||||
* Reduce neighbor line opacity by @l5yth in <https://github.com/l5yth/potato-mesh/pull/226>
|
||||
* Visualize neighbor connections on map canvas by @l5yth in <https://github.com/l5yth/potato-mesh/pull/224>
|
||||
* Add clear control to filter input by @l5yth in <https://github.com/l5yth/potato-mesh/pull/225>
|
||||
* Handle Bluetooth shutdown hangs gracefully by @l5yth in <https://github.com/l5yth/potato-mesh/pull/221>
|
||||
* Adjust mesh priorities and receive topics by @l5yth in <https://github.com/l5yth/potato-mesh/pull/220>
|
||||
* Add BLE and fallback mesh interface handling by @l5yth in <https://github.com/l5yth/potato-mesh/pull/219>
|
||||
* Add neighbor info ingestion and API endpoints by @l5yth in <https://github.com/l5yth/potato-mesh/pull/218>
|
||||
* Add debug logs for unknown node creation and last-heard updates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/214>
|
||||
* Update node last seen when events are received by @l5yth in <https://github.com/l5yth/potato-mesh/pull/212>
|
||||
* Improve debug logging for node and telemetry data by @l5yth in <https://github.com/l5yth/potato-mesh/pull/213>
|
||||
* Normalize stored message debug output by @l5yth in <https://github.com/l5yth/potato-mesh/pull/211>
|
||||
* Stop repeating ingestor node info snapshot and timestamp debug logs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/210>
|
||||
* Add telemetry API and ingestion support by @l5yth in <https://github.com/l5yth/potato-mesh/pull/205>
|
||||
* Add private mode to hide chat and message APIs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/204>
|
||||
* Handle offline-ready map fallback by @l5yth in <https://github.com/l5yth/potato-mesh/pull/202>
|
||||
* Add linux/armv7 container builds and configuration options by @l5yth in <https://github.com/l5yth/potato-mesh/pull/201>
|
||||
* Update Docker documentation by @l5yth in <https://github.com/l5yth/potato-mesh/pull/200>
|
||||
* Update node last seen when ingesting encrypted messages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/198>
|
||||
* Fix api in readme by @l5yth in <https://github.com/l5yth/potato-mesh/pull/197>
|
||||
|
||||
## v0.3.0
|
||||
|
||||
* Add connection recovery for TCP interface by @l5yth in <https://github.com/l5yth/potato-mesh/pull/186>
|
||||
* Bump version to 0.3 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/191>
|
||||
* Pgrade styles and fix interface issues by @l5yth in <https://github.com/l5yth/potato-mesh/pull/190>
|
||||
* Some updates in the front by @dkorotkih2014-hub in <https://github.com/l5yth/potato-mesh/pull/188>
|
||||
* Update last heard on node entry change by @l5yth in <https://github.com/l5yth/potato-mesh/pull/185>
|
||||
* Populate chat metadata for unknown nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/182>
|
||||
* Update role color theme to latest palette by @l5yth in <https://github.com/l5yth/potato-mesh/pull/183>
|
||||
* Add placeholder nodes for unknown senders by @l5yth in <https://github.com/l5yth/potato-mesh/pull/181>
|
||||
* Update role colors and ordering for firmware 2.7.10 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/180>
|
||||
* Handle plain IP addresses in mesh TCP detection by @l5yth in <https://github.com/l5yth/potato-mesh/pull/154>
|
||||
* Handle encrypted messages by @l5yth in <https://github.com/l5yth/potato-mesh/pull/173>
|
||||
* Add fallback display names for unnamed nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/171>
|
||||
* Ensure routers render above other node types by @l5yth in <https://github.com/l5yth/potato-mesh/pull/169>
|
||||
* Move lint checks after tests in CI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/168>
|
||||
* Handle proto values in nodeinfo payloads by @l5yth in <https://github.com/l5yth/potato-mesh/pull/167>
|
||||
* Remove raw payload storage from database schema by @l5yth in <https://github.com/l5yth/potato-mesh/pull/166>
|
||||
* Add POSITION_APP ingestion and API support by @l5yth in <https://github.com/l5yth/potato-mesh/pull/160>
|
||||
* Add support for NODEINFO_APP packets by @l5yth in <https://github.com/l5yth/potato-mesh/pull/159>
|
||||
* Derive SEO metadata from existing config values by @l5yth in <https://github.com/l5yth/potato-mesh/pull/153>
|
||||
* Tests: create helper script to dump all mesh data from serial by @l5yth in <https://github.com/l5yth/potato-mesh/pull/152>
|
||||
* Limit chat log to recent entries by @l5yth in <https://github.com/l5yth/potato-mesh/pull/151>
|
||||
* Require time library before formatting ISO timestamps by @l5yth in <https://github.com/l5yth/potato-mesh/pull/149>
|
||||
* Define docker compose network by @l5yth in <https://github.com/l5yth/potato-mesh/pull/148>
|
||||
* Fix sqlite3 native extension on Alpine by @l5yth in <https://github.com/l5yth/potato-mesh/pull/146>
|
||||
* Fix web app startup binding by @l5yth in <https://github.com/l5yth/potato-mesh/pull/147>
|
||||
* Ensure sqlite3 builds from source on Alpine by @l5yth in <https://github.com/l5yth/potato-mesh/pull/145>
|
||||
* Support mock serial interface in CI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/143>
|
||||
* Fix Docker workflow matrix for supported platforms by @l5yth in <https://github.com/l5yth/potato-mesh/pull/142>
|
||||
* Add clickable role filters to the map legend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/140>
|
||||
* Rebuild chat log on each refresh by @l5yth in <https://github.com/l5yth/potato-mesh/pull/139>
|
||||
* Fix: retain alpine runtime libs after removing build deps by @l5yth in <https://github.com/l5yth/potato-mesh/pull/138>
|
||||
* Fix: support windows ingestor build by @l5yth in <https://github.com/l5yth/potato-mesh/pull/136>
|
||||
* Fix: use supported ruby image by @l5yth in <https://github.com/l5yth/potato-mesh/pull/135>
|
||||
* Feat: Add comprehensive Docker support by @trose in <https://github.com/l5yth/potato-mesh/pull/122>
|
||||
* Chore: bump version to 0.2.1 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/134>
|
||||
* Fix dark mode tile styling on new map tiles by @l5yth in <https://github.com/l5yth/potato-mesh/pull/132>
|
||||
* Switch map tiles to OSM HOT and add theme filters by @l5yth in <https://github.com/l5yth/potato-mesh/pull/130>
|
||||
* Add footer version display by @l5yth in <https://github.com/l5yth/potato-mesh/pull/128>
|
||||
* Add responsive controls for map legend by @l5yth in <https://github.com/l5yth/potato-mesh/pull/129>
|
||||
* Update changelog by @l5yth in <https://github.com/l5yth/potato-mesh/pull/119>
|
||||
|
||||
## v0.2.0
|
||||
|
||||
* Update readme for 0.2 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/118>
|
||||
* Add PotatoMesh logo to header and favicon by @l5yth in <https://github.com/l5yth/potato-mesh/pull/117>
|
||||
* Harden API auth and request limits by @l5yth in <https://github.com/l5yth/potato-mesh/pull/116>
|
||||
* Add client-side sorting to node table by @l5yth in <https://github.com/l5yth/potato-mesh/pull/114>
|
||||
* Add short name overlay for node details by @l5yth in <https://github.com/l5yth/potato-mesh/pull/111>
|
||||
* Adjust python ingestor interval to 60 seconds by @l5yth in <https://github.com/l5yth/potato-mesh/pull/112>
|
||||
* Hide location columns on medium screens by @l5yth in <https://github.com/l5yth/potato-mesh/pull/109>
|
||||
* Handle message updates based on sender info by @l5yth in <https://github.com/l5yth/potato-mesh/pull/108>
|
||||
* Prioritize node posts in queued API updates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/107>
|
||||
* Add auto-refresh toggle to UI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/105>
|
||||
* Adjust Leaflet popup styling for dark mode by @l5yth in <https://github.com/l5yth/potato-mesh/pull/104>
|
||||
* Add site info overlay by @l5yth in <https://github.com/l5yth/potato-mesh/pull/103>
|
||||
* Add long name tooltip to short name badge by @l5yth in <https://github.com/l5yth/potato-mesh/pull/102>
|
||||
* Ensure node numeric aliases are derived from canonical IDs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/101>
|
||||
* Chore: clean up repository by @l5yth in <https://github.com/l5yth/potato-mesh/pull/96>
|
||||
* Handle SQLite busy errors when upserting nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/100>
|
||||
* Configure Sinatra logging level from DEBUG flag by @l5yth in <https://github.com/l5yth/potato-mesh/pull/97>
|
||||
* Add penetration tests for authentication and SQL injection by @l5yth in <https://github.com/l5yth/potato-mesh/pull/95>
|
||||
* Document Python and Ruby source modules by @l5yth in <https://github.com/l5yth/potato-mesh/pull/94>
|
||||
* Add tests covering mesh helper edge cases by @l5yth in <https://github.com/l5yth/potato-mesh/pull/93>
|
||||
* Fix py code cov by @l5yth in <https://github.com/l5yth/potato-mesh/pull/92>
|
||||
* Add Codecov reporting to Python CI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/91>
|
||||
* Skip null identifiers when selecting packet fields by @l5yth in <https://github.com/l5yth/potato-mesh/pull/88>
|
||||
* Create python yml ga by @l5yth in <https://github.com/l5yth/potato-mesh/pull/90>
|
||||
* Add unit tests for mesh ingestor script by @l5yth in <https://github.com/l5yth/potato-mesh/pull/89>
|
||||
* Add coverage for debug logging on messages without sender by @l5yth in <https://github.com/l5yth/potato-mesh/pull/86>
|
||||
* Handle concurrent node snapshot updates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/85>
|
||||
* Fix ingestion mapping for message sender IDs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/84>
|
||||
* Add coverage for API authentication and payload edge cases by @l5yth in <https://github.com/l5yth/potato-mesh/pull/83>
|
||||
* Add JUnit test reporting to Ruby CI by @l5yth in <https://github.com/l5yth/potato-mesh/pull/82>
|
||||
* Configure SimpleCov reporting for Codecov by @l5yth in <https://github.com/l5yth/potato-mesh/pull/81>
|
||||
* Update codecov job by @l5yth in <https://github.com/l5yth/potato-mesh/pull/80>
|
||||
* Fix readme badges by @l5yth in <https://github.com/l5yth/potato-mesh/pull/79>
|
||||
* Add Codecov upload step to Ruby workflow by @l5yth in <https://github.com/l5yth/potato-mesh/pull/78>
|
||||
* Add Apache license headers to source files by @l5yth in <https://github.com/l5yth/potato-mesh/pull/77>
|
||||
* Add integration specs for node and message APIs by @l5yth in <https://github.com/l5yth/potato-mesh/pull/76>
|
||||
* Docs: update for 0.2.0 release by @l5yth in <https://github.com/l5yth/potato-mesh/pull/75>
|
||||
* Create ruby workflow by @l5yth in <https://github.com/l5yth/potato-mesh/pull/74>
|
||||
* Add RSpec smoke tests for app boot and database init by @l5yth in <https://github.com/l5yth/potato-mesh/pull/73>
|
||||
* Align refresh controls with status text by @l5yth in <https://github.com/l5yth/potato-mesh/pull/72>
|
||||
* Improve mobile layout by @l5yth in <https://github.com/l5yth/potato-mesh/pull/68>
|
||||
* Normalize message sender IDs using node numbers by @l5yth in <https://github.com/l5yth/potato-mesh/pull/67>
|
||||
* Style: condense node table by @l5yth in <https://github.com/l5yth/potato-mesh/pull/65>
|
||||
* Log debug details for messages without sender by @l5yth in <https://github.com/l5yth/potato-mesh/pull/64>
|
||||
* Fix nested dataclass serialization for node snapshots by @l5yth in <https://github.com/l5yth/potato-mesh/pull/63>
|
||||
* Log node object on snapshot update failure by @l5yth in <https://github.com/l5yth/potato-mesh/pull/62>
|
||||
* Initialize database on startup by @l5yth in <https://github.com/l5yth/potato-mesh/pull/61>
|
||||
* Send mesh data to Potatomesh API by @l5yth in <https://github.com/l5yth/potato-mesh/pull/60>
|
||||
* Convert boolean flags for SQLite binding by @l5yth in <https://github.com/l5yth/potato-mesh/pull/59>
|
||||
* Use packet id as message primary key by @l5yth in <https://github.com/l5yth/potato-mesh/pull/58>
|
||||
* Add message ingestion API and stricter auth by @l5yth in <https://github.com/l5yth/potato-mesh/pull/56>
|
||||
* Feat: parameterize community info by @l5yth in <https://github.com/l5yth/potato-mesh/pull/55>
|
||||
* Feat: add dark mode toggle by @l5yth in <https://github.com/l5yth/potato-mesh/pull/54>
|
||||
|
||||
## v0.1.0
|
||||
|
||||
* Show daily node count in title and header by @l5yth in <https://github.com/l5yth/potato-mesh/pull/49>
|
||||
* Add daily date separators to chat log by @l5yth in <https://github.com/l5yth/potato-mesh/pull/47>
|
||||
* Feat: make frontend responsive for mobile by @l5yth in <https://github.com/l5yth/potato-mesh/pull/46>
|
||||
* Harden mesh utilities by @l5yth in <https://github.com/l5yth/potato-mesh/pull/45>
|
||||
* Filter out distant nodes from Berlin map view by @l5yth in <https://github.com/l5yth/potato-mesh/pull/43>
|
||||
* Display filtered active node counts in #MediumFast subheading by @l5yth in <https://github.com/l5yth/potato-mesh/pull/44>
|
||||
* Limit chat log and highlight short names by role by @l5yth in <https://github.com/l5yth/potato-mesh/pull/42>
|
||||
* Fix string/integer comparison in node query by @l5yth in <https://github.com/l5yth/potato-mesh/pull/40>
|
||||
* Escape chat message and node entries by @l5yth in <https://github.com/l5yth/potato-mesh/pull/39>
|
||||
* Sort chat entries by timestamp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/38>
|
||||
* Feat: append messages to chat log by @l5yth in <https://github.com/l5yth/potato-mesh/pull/36>
|
||||
* Normalize future timestamps for nodes by @l5yth in <https://github.com/l5yth/potato-mesh/pull/35>
|
||||
* Optimize web frontend and Ruby app by @l5yth in <https://github.com/l5yth/potato-mesh/pull/32>
|
||||
* Add messages API endpoint with node details by @l5yth in <https://github.com/l5yth/potato-mesh/pull/33>
|
||||
* Clamp node timestamps and sync last_heard with position time by @l5yth in <https://github.com/l5yth/potato-mesh/pull/31>
|
||||
* Refactor: replace deprecated utcfromtimestamp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/30>
|
||||
* Add optional debug logging for node and message operations by @l5yth in <https://github.com/l5yth/potato-mesh/pull/29>
|
||||
* Data: enable serial collection of messages on channel 0 by @l5yth in <https://github.com/l5yth/potato-mesh/pull/25>
|
||||
* Add first_heard timestamp by @l5yth in <https://github.com/l5yth/potato-mesh/pull/23>
|
||||
* Add persistent footer with contact information by @l5yth in <https://github.com/l5yth/potato-mesh/pull/22>
|
||||
* Sort initial chat entries by last-heard by @l5yth in <https://github.com/l5yth/potato-mesh/pull/20>
|
||||
* Display position time in relative 'time ago' format by @l5yth in <https://github.com/l5yth/potato-mesh/pull/19>
|
||||
* Adjust marker size and map tile opacity by @l5yth in <https://github.com/l5yth/potato-mesh/pull/18>
|
||||
* Add chat box for node notifications by @l5yth in <https://github.com/l5yth/potato-mesh/pull/17>
|
||||
* Color markers by role with grayscale map by @l5yth in <https://github.com/l5yth/potato-mesh/pull/16>
|
||||
* Default missing node role to client by @l5yth in <https://github.com/l5yth/potato-mesh/pull/15>
|
||||
* Show live node count in nodes page titles by @l5yth in <https://github.com/l5yth/potato-mesh/pull/14>
|
||||
* Filter stale nodes and add live search by @l5yth in <https://github.com/l5yth/potato-mesh/pull/13>
|
||||
* Remove raw node JSON column by @l5yth in <https://github.com/l5yth/potato-mesh/pull/12>
|
||||
* Add JSON ingest API for node updates by @l5yth in <https://github.com/l5yth/potato-mesh/pull/11>
|
||||
* Ignore Python __pycache__ directories by @l5yth in <https://github.com/l5yth/potato-mesh/pull/10>
|
||||
* Feat: load nodes from json for tests by @l5yth in <https://github.com/l5yth/potato-mesh/pull/8>
|
||||
* Handle dataclass fields in node snapshots by @l5yth in <https://github.com/l5yth/potato-mesh/pull/6>
|
||||
* Add index page and /nodes route for node map by @l5yth in <https://github.com/l5yth/potato-mesh/pull/4>
|
||||
68
CLAUDE.md
Normal file
@@ -0,0 +1,68 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# Repository Guidelines
|
||||
|
||||
Keep code as modular as possible to reduce duplication and improve reusability and readability — this applies to tests as well as production code. If a module grows large, split it into a submodule structure. Prefer composing small, single-purpose units over monolithic files.
|
||||
|
||||
Make sure all tests pass for Python (`pytest`), Ruby (`rspec`), and JavaScript (`npm test`).
|
||||
|
||||
All code must be 100% unit tested — every line, branch, and code path must have a unit test. "100%" is the floor, not the ceiling: smoke tests, integration tests, and end-to-end tests come on top of that. No new code ships without matching unit tests.
|
||||
|
||||
All code must be 100% documented according to the language's API-doc standard (PDoc for Python, RDoc for Ruby, JSDoc for JavaScript, rustdoc for Rust, dartdoc for Dart). Documentation must be sufficient to generate complete API docs from source. In addition to API-level docs, add inline comments wherever the logic is not immediately self-evident.
|
||||
|
||||
Every file in the repository must carry an Apache v2 license notice using the exact string `Copyright © 2025-26 l5yth & contributors`. **Source-code files** (`.rb`, `.py`, `.js`, `.rs`, `.dart`, etc.) must include the full Apache v2 license header block. **Non-source files** (docs, configs, YAML, TOML, Dockerfiles, etc.) must include a short 2-line Apache v2 notice (copyright line + license reference).
|
||||
|
||||
Run linters for Python (`black`) and Ruby (`rufo`) to ensure consistent code formatting.
|
||||
|
||||
## Project Structure & Module Organization
|
||||
The repository splits runtime and ingestion logic. `web/` holds the Sinatra dashboard (Ruby code in `lib/potato_mesh`, views in `views/`, static bundles in `public/`).
|
||||
|
||||
`data/` hosts the Python Meshtastic ingestor plus migrations and CLI scripts. The ingestor is structured as the `data/mesh_ingestor/` package with the following key modules: `daemon.py` (main loop), `handlers.py` (packet processing), `interfaces.py` (interface helpers), `config.py` (env-driven config), `events.py` (TypedDict event schemas), `mesh_protocol.py` (MeshProtocol base), `node_identity.py` (canonical node ID utilities), `decode_payload.py` (CLI protobuf decoder), and the `protocols/` subpackage (currently `meshtastic.py`). API contracts for all POST ingest routes are documented in `data/mesh_ingestor/CONTRACTS.md`. API fixtures and end-to-end harnesses live in `tests/`. Dockerfiles and compose files support containerized workflows.
|
||||
|
||||
`matrix/` contains the Rust Matrix bridge; build with `cargo build --release` or `docker build -f matrix/Dockerfile .`, and keep bridge config under `matrix/Config.toml` when running locally.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
Run dependency installs inside `web/`: `bundle install` for gems and `npm ci` for JavaScript tooling. Start the app with `cd web && API_TOKEN=dev ./app.sh` for local work or `bundle exec rackup -p 41447` when integrating elsewhere.
|
||||
|
||||
Prep ingestion with `python -m venv .venv && pip install -r data/requirements.txt`; `./data/mesh.sh` streams from live radios. `docker-compose -f docker-compose.dev.yml up` brings up the full stack.
|
||||
|
||||
Container images publish via `.github/workflows/docker.yml` as `potato-mesh-{service}-linux-$arch` (`web`, `ingestor`, `matrix-bridge`), using the Dockerfiles in `web/`, `data/`, and `matrix/`.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
Use two-space indentation for Ruby and keep `# frozen_string_literal: true` at the top of new files. Keep Ruby classes/modules in `CamelCase`, filenames in `snake_case.rb`, and feature specs in `*_spec.rb`.
|
||||
|
||||
JavaScript follows ES modules under `public/assets/js`; co-locate components with `__tests__` folders and use kebab-case filenames. Format Ruby via `bundle exec rufo .` and Python via `black`. Skip committing generated coverage artifacts.
|
||||
|
||||
## Flutter Mobile App (`app/`)
|
||||
The Flutter client lives in `app/`. Keep only the mobile targets (`android/`, `ios/`) under version control unless you explicitly support other platforms. Do not commit Flutter build outputs or editor cruft (`.dart_tool/`, `.flutter-plugins-dependencies`, `.idea/`, `.metadata`, `*.iml`, `.fvmrc` if unused).
|
||||
|
||||
Install dependencies with `cd app && flutter pub get`; format with `dart format .` and lint via `flutter analyze`. Run tests with `cd app && flutter test` and keep widget/unit coverage high—no new code without tests. Commit `pubspec.lock` and analysis options so toolchains stay consistent.
|
||||
|
||||
## Testing Guidelines
|
||||
Ruby specs run with `cd web && bundle exec rspec`, producing SimpleCov output in `coverage/`. Front-end behaviour is verified through Node’s test runner: `cd web && npm test` writes V8 coverage and JUnit XML under `reports/`.
|
||||
|
||||
The ingestion layer is tested with `pytest -q tests/`; leave fixtures in `tests/` untouched so CI can replay them. The suite includes both integration tests (`test_mesh.py`) and focused unit tests — `test_events_unit.py` (TypedDict schemas), `test_provider_unit.py` (Provider protocol conformance and `MeshtasticProvider`), `test_node_identity_unit.py` (canonical ID helpers), `test_daemon_unit.py`, `test_serialization_unit.py`, and `test_decode_payload.py`. New features should ship with matching specs and updated integration checks.
|
||||
|
||||
## Adding a New Ingestor Protocol
|
||||
The `data/mesh_ingestor/mesh_protocol.py` module defines a `@runtime_checkable` `MeshProtocol` class with five members: `name` (str), `subscribe()`, `connect(*, active_candidate)`, `extract_host_node_id(iface)`, and `node_snapshot_items(iface)`. To add a new backend (e.g. Reticulum):
|
||||
|
||||
1. Create `data/mesh_ingestor/protocols/<name>.py` with a class satisfying the `MeshProtocol` interface.
|
||||
2. Register it in `data/mesh_ingestor/protocols/__init__.py`.
|
||||
3. Pass an instance via `daemon.main(provider=...)` or make it the default in `main()`.
|
||||
4. Cover the protocol with unit tests in `tests/test_provider_unit.py` — at minimum an `isinstance(..., MeshProtocol)` conformance check and any retry/error-handling paths.
|
||||
|
||||
Consult `data/mesh_ingestor/CONTRACTS.md` for the canonical event shapes all protocols must emit.
|
||||
|
||||
## GitHub Configuration Standards
|
||||
Every language used in the repository must have a Dependabot entry checking for dependency updates on a **weekly** schedule. Keep the Dependabot config up to date as new languages or package ecosystems are added.
|
||||
|
||||
Codecov must be configured with a **100% coverage target** and a **10% threshold** (i.e. a drop of more than 10 percentage points fails the check). The `codecov.yml` should enforce this on both patch and project coverage.
|
||||
|
||||
Every service/component must have at least one GitHub Actions workflow that **builds and runs tests on pull requests against `main` and on direct pushes to `main`**. Workflows should cover all relevant test suites (Python, Ruby, JS, Rust, Flutter) for the components they touch.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
Commits should stay imperative and reference issues the way history does (`Add chat log entries... (#408)`). Squash noisy work-in-progress commits before pushing. Pull requests need a concise summary, screenshots or curl traces for UI/API tweaks, and links to tracked issues. Paste the command output for the test suites you ran and mention configuration toggles (`API_TOKEN`, `PRIVATE`) reviewers must set.
|
||||
|
||||
## Security & Configuration Tips
|
||||
Never commit real API tokens or `.sqlite` dumps; use `.env.local` files ignored by Git. Confirm env defaults (`API_TOKEN`, `INSTANCE_DOMAIN`, `PRIVATE`) before deploying, and set `FEDERATION=0` when staging private nodes. Review `PROMETHEUS.md` when exposing metrics so scrape endpoints stay internal.
|
||||
127
DOCKER.md
Normal file
@@ -0,0 +1,127 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# PotatoMesh Docker Guide
|
||||
|
||||
PotatoMesh publishes ready-to-run container images to the GitHub Packages container
|
||||
registry (GHCR). You do not need to clone the repository to deploy them—Compose
|
||||
will pull the latest release images for you.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine 24+ or Docker Desktop with the Compose plugin
|
||||
- Access to `/dev/ttyACM*` (or equivalent) if you plan to attach a Meshtastic
|
||||
device to the ingestor container
|
||||
- An API token that authorises the ingestor to post to your PotatoMesh instance
|
||||
|
||||
## Images on GHCR
|
||||
|
||||
| Service | Image |
|
||||
|----------|----------------------------------------------------------------------------------------------------------------|
|
||||
| Web UI | `ghcr.io/l5yth/potato-mesh-web-linux-amd64:<tag>` (e.g. `latest`, `0.6.0`, `v0.6.0`, or `0.7.0-rc1`) |
|
||||
| Ingestor | `ghcr.io/l5yth/potato-mesh-ingestor-linux-amd64:<tag>` (e.g. `latest`, `0.6.0`, `v0.6.0`, or `0.7.0-rc1`) |
|
||||
|
||||
Images are published for every tagged release. Stable builds receive both
|
||||
semantic version tags (for example `0.6.0`) and a matching `v`-prefixed tag (for
|
||||
example `v0.6.0`), plus a `latest` tag that tracks the newest stable release.
|
||||
Pre-release tags (for example `-rc`, `-beta`, `-alpha`, or `-dev` suffixes) are
|
||||
published only with their explicit version strings (`0.7.0-rc1` and `v0.7.0-rc1`
|
||||
in this example) and do **not** advance `latest`. Pin the versioned tags when
|
||||
you need a specific build.
|
||||
|
||||
## Configure environment
|
||||
|
||||
Create a `.env` file alongside your Compose file and populate the variables you
|
||||
need. At a minimum you must set `API_TOKEN` so the ingestor can authenticate
|
||||
against the web API.
|
||||
|
||||
```env
|
||||
API_TOKEN=replace-with-a-strong-token
|
||||
SITE_NAME=PotatoMesh Demo
|
||||
CONNECTION=/dev/ttyACM0
|
||||
INSTANCE_DOMAIN=mesh.example.org
|
||||
```
|
||||
|
||||
Additional environment variables are optional:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `API_TOKEN` | _required_ | Shared secret used by the ingestor and API clients for authenticated `POST` requests. |
|
||||
| `INSTANCE_DOMAIN` | _auto-detected_ | Public hostname (optionally with port) advertised by the web UI, metadata, and API responses. |
|
||||
| `SITE_NAME` | `"PotatoMesh Demo"` | Title and branding surfaced in the web UI. |
|
||||
| `CHANNEL` | `"#LongFast"` | Default LoRa channel label displayed on the dashboard. |
|
||||
| `FREQUENCY` | `"915MHz"` | Default LoRa frequency description shown in the UI. |
|
||||
| `CONTACT_LINK` | `"#potatomesh:dod.ngo"` | Chat link or Matrix room alias rendered in UI footers and overlays. |
|
||||
| `MAP_CENTER` | `38.761944,-27.090833` | Latitude and longitude that centre the map view. |
|
||||
| `MAP_ZOOM` | _unset_ | Fixed Leaflet zoom (disables the auto-fit checkbox when set). |
|
||||
| `MAX_DISTANCE` | `42` | Maximum relationship distance (km) before edges are hidden. |
|
||||
| `DEBUG` | `0` | Enables verbose logging across services when set to `1`. |
|
||||
| `ALLOWED_CHANNELS` | _unset_ | Comma-separated channel names the ingestor accepts; other channels are skipped before hidden filters. |
|
||||
| `HIDDEN_CHANNELS` | _unset_ | Comma-separated channel names the ingestor skips when forwarding packets. |
|
||||
| `FEDERATION` | `1` | Controls whether the instance announces itself and crawls peers (`1`) or stays isolated (`0`). |
|
||||
| `PRIVATE` | `0` | Restricts public visibility and disables chat/message endpoints when set to `1`. |
|
||||
| `CONNECTION` | `/dev/ttyACM0` | Serial device, TCP endpoint, or Bluetooth target used by the ingestor to reach the radio. |
|
||||
|
||||
The ingestor posts to the URL configured via `INSTANCE_DOMAIN` (defaulting to
|
||||
`http://web:41447` in the provided compose file). Use `CHANNEL_INDEX` to select
|
||||
a LoRa channel on serial or Bluetooth connections.
|
||||
|
||||
## Docker Compose file
|
||||
|
||||
Use the `docker-compose.yml` file provided in the repository (or download the
|
||||
[raw file from GitHub](https://raw.githubusercontent.com/l5yth/potato-mesh/main/docker-compose.yml)).
|
||||
It already references the published GHCR images, defines persistent volumes for
|
||||
data, configuration, and logs, and includes optional bridge-profile services for
|
||||
environments that require classic port mapping. Place this file in the same
|
||||
directory as your `.env` file so Compose can pick up both.
|
||||
|
||||
The dedicated configuration volume binds to `/app/.config/potato-mesh` inside
|
||||
the container. This path stores the instance private key and staged
|
||||
`/.well-known/potato-mesh` documents. Because the volume persists independently
|
||||
of container lifecycle events, generated credentials are not replaced on reboot
|
||||
or re-deploy.
|
||||
|
||||
The `potatomesh_pages` volume mounts to `/app/pages` and holds operator-managed
|
||||
Markdown files that are rendered as static content pages in the web UI. On first
|
||||
start the default `1-about.md` page is copied from the image into the volume.
|
||||
You can add, edit, or remove `.md` files in this volume to customise your
|
||||
instance's navigation. To use a host directory instead of a named volume, replace
|
||||
the volume entry with a bind mount:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./my-pages:/app/pages
|
||||
```
|
||||
|
||||
## Start the stack
|
||||
|
||||
From the directory containing the Compose file:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Docker automatically pulls the GHCR images when they are not present locally.
|
||||
The dashboard becomes available at `http://127.0.0.1:41447`. Use the bridge
|
||||
profile when you need to map the port explicitly:
|
||||
|
||||
```bash
|
||||
COMPOSE_PROFILES=bridge docker compose up -d
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Serial device permissions (Linux/macOS):** grant access with `sudo chmod 666
|
||||
/dev/ttyACM0` or add your user to the `dialout` group.
|
||||
- **Port already in use:** identify the conflicting service with `sudo lsof -i
|
||||
:41447`.
|
||||
- **Viewing logs:** `docker compose logs -f` tails output from both services.
|
||||
|
||||
For general Docker support, consult the [Docker Compose documentation](https://docs.docker.com/compose/).
|
||||
114
Dockerfile
Normal file
@@ -0,0 +1,114 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
# NOTE: This Dockerfile is kept for backward compatibility. The canonical build
|
||||
# instructions live in `web/Dockerfile`; keep the two files in sync.
|
||||
|
||||
# Main application builder stage
|
||||
FROM ruby:3.3-alpine AS builder
|
||||
|
||||
# Ensure native extensions are built against musl libc rather than
|
||||
# using glibc precompiled binaries (which fail on Alpine).
|
||||
ENV BUNDLE_FORCE_RUBY_PLATFORM=true
|
||||
|
||||
# Install build dependencies and SQLite3
|
||||
RUN apk add --no-cache \
|
||||
build-base \
|
||||
python3 \
|
||||
py3-pip \
|
||||
py3-virtualenv \
|
||||
sqlite-dev \
|
||||
linux-headers \
|
||||
pkgconfig
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy Gemfile and install dependencies
|
||||
COPY web/Gemfile web/Gemfile.lock* ./
|
||||
|
||||
# Install gems with SQLite3 support
|
||||
RUN bundle config set --local force_ruby_platform true && \
|
||||
bundle config set --local without 'development test' && \
|
||||
bundle install --jobs=4 --retry=3
|
||||
|
||||
# Install Meshtastic decoder dependencies in a dedicated venv
|
||||
RUN python3 -m venv /opt/meshtastic-venv && \
|
||||
/opt/meshtastic-venv/bin/pip install --no-cache-dir meshtastic protobuf
|
||||
|
||||
# Production stage
|
||||
FROM ruby:3.3-alpine AS production
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
sqlite \
|
||||
tzdata \
|
||||
curl
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1000 -S potatomesh && \
|
||||
adduser -u 1000 -S potatomesh -G potatomesh
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy installed gems from builder stage
|
||||
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
||||
COPY --from=builder /opt/meshtastic-venv /opt/meshtastic-venv
|
||||
|
||||
# Copy application code (excluding the Dockerfile which is not required at runtime)
|
||||
COPY --chown=potatomesh:potatomesh web/app.rb ./
|
||||
COPY --chown=potatomesh:potatomesh web/app.sh ./
|
||||
COPY --chown=potatomesh:potatomesh web/Gemfile ./
|
||||
COPY --chown=potatomesh:potatomesh web/Gemfile.lock* ./
|
||||
COPY --chown=potatomesh:potatomesh web/lib ./lib
|
||||
COPY --chown=potatomesh:potatomesh web/spec ./spec
|
||||
COPY --chown=potatomesh:potatomesh web/public ./public
|
||||
COPY --chown=potatomesh:potatomesh web/views ./views
|
||||
COPY --chown=potatomesh:potatomesh web/scripts ./scripts
|
||||
|
||||
# Copy SQL schema files from data directory
|
||||
COPY --chown=potatomesh:potatomesh data/*.sql /data/
|
||||
COPY --chown=potatomesh:potatomesh data/mesh_ingestor/decode_payload.py /app/data/mesh_ingestor/decode_payload.py
|
||||
|
||||
# Create data and configuration directories with correct ownership
|
||||
RUN mkdir -p /app/.local/share/potato-mesh \
|
||||
&& mkdir -p /app/.config/potato-mesh/well-known \
|
||||
&& chown -R potatomesh:potatomesh /app/.local/share /app/.config
|
||||
|
||||
# Switch to non-root user
|
||||
USER potatomesh
|
||||
|
||||
# Expose port
|
||||
EXPOSE 41447
|
||||
|
||||
# Default environment variables (can be overridden by host)
|
||||
ENV RACK_ENV=production \
|
||||
APP_ENV=production \
|
||||
MESHTASTIC_PYTHON=/opt/meshtastic-venv/bin/python \
|
||||
XDG_DATA_HOME=/app/.local/share \
|
||||
XDG_CONFIG_HOME=/app/.config \
|
||||
SITE_NAME="PotatoMesh Demo" \
|
||||
CHANNEL="#LongFast" \
|
||||
FREQUENCY="915MHz" \
|
||||
MAP_CENTER="38.761944,-27.090833" \
|
||||
MAP_ZOOM="" \
|
||||
MAX_DISTANCE=42 \
|
||||
CONTACT_LINK="#potatomesh:dod.ngo" \
|
||||
DEBUG=0
|
||||
|
||||
# Start the application
|
||||
CMD ["ruby", "app.rb", "-p", "41447", "-o", "0.0.0.0"]
|
||||
4
LICENSE
@@ -33,7 +33,7 @@
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
Object form, made available under the Licen2se, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright (C) 2025 l5yth
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
103
PROMETHEUS.md
Normal file
@@ -0,0 +1,103 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# Prometheus Monitoring for PotatoMesh
|
||||
|
||||
PotatoMesh exposes runtime telemetry through a dedicated Prometheus endpoint so you can
|
||||
observe message flow, node health, and geospatial metadata alongside the rest of your
|
||||
infrastructure. This guide explains how the exporter is wired into the web
|
||||
application, which metrics are available, and how to integrate the endpoint with a
|
||||
Prometheus server.
|
||||
|
||||
## Runtime integration
|
||||
|
||||
The Sinatra application automatically loads the `prometheus-client` gem and mounts the
|
||||
collector and exporter middlewares during boot. No additional configuration is
|
||||
required to enable the `/metrics` endpoint—running the web application is enough to
|
||||
serve Prometheus data on the same port as the dashboard. The middleware pair both
|
||||
collects default Rack statistics and publishes PotatoMesh-specific gauges and
|
||||
counters that are updated whenever the ingestors process new node records.
|
||||
|
||||
A background refresh is triggered during start-up via
|
||||
`update_all_prometheus_metrics_from_nodes`, which seeds the gauges based on the latest
|
||||
state in the database. Subsequent POST requests to the ingest APIs update each metric
|
||||
in near real time.
|
||||
|
||||
## Selecting which nodes are exported
|
||||
|
||||
To avoid creating high-cardinality time series, PotatoMesh does not export per-node
|
||||
metrics unless you opt in by providing node identifiers. Control this behaviour with
|
||||
the `PROM_REPORT_IDS` environment variable:
|
||||
|
||||
- Leave the variable unset or blank to only export aggregate gauges such as the total
|
||||
node count.
|
||||
- Set `PROM_REPORT_IDS=*` to export metrics for every node in the database.
|
||||
- Provide a comma-separated list (for example `PROM_REPORT_IDS=ABCD1234,EFGH5678`) to
|
||||
expose metrics for specific nodes.
|
||||
|
||||
The selection applies to both the initial refresh and the incremental updates handled
|
||||
by the ingest pipeline.
|
||||
|
||||
## Available metrics
|
||||
|
||||
| Metric name | Type | Labels | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `meshtastic_messages_total` | Counter | _none_ | Increments each time the ingest pipeline accepts a new message payload. |
|
||||
| `meshtastic_nodes` | Gauge | _none_ | Tracks the number of nodes currently stored in the database. |
|
||||
| `meshtastic_node` | Gauge | `node`, `short_name`, `long_name`, `hw_model`, `role` | Reports a node as present (value `1`) along with identity metadata. |
|
||||
| `meshtastic_node_battery_level` | Gauge | `node` | Most recent battery percentage reported by the node. |
|
||||
| `meshtastic_node_voltage` | Gauge | `node` | Most recent battery voltage reading. |
|
||||
| `meshtastic_node_uptime_seconds` | Gauge | `node` | Uptime reported by the device in seconds. |
|
||||
| `meshtastic_node_channel_utilization` | Gauge | `node` | Latest channel utilisation ratio supplied by the node. |
|
||||
| `meshtastic_node_transmit_air_utilization` | Gauge | `node` | Proportion of on-air time spent transmitting. |
|
||||
| `meshtastic_node_latitude` | Gauge | `node` | Latitude component of the last known position. |
|
||||
| `meshtastic_node_longitude` | Gauge | `node` | Longitude component of the last known position. |
|
||||
| `meshtastic_node_altitude` | Gauge | `node` | Altitude (in metres) of the last known position. |
|
||||
|
||||
All per-node gauges are only emitted for identifiers included in `PROM_REPORT_IDS`.
|
||||
Some values require telemetry packets to be present—for example, devices must provide
|
||||
metrics or positional updates before the related gauges appear.
|
||||
|
||||
## Accessing the `/metrics` endpoint
|
||||
|
||||
Once the application is running, query the exporter directly:
|
||||
|
||||
```bash
|
||||
curl http://localhost:41447/metrics
|
||||
```
|
||||
|
||||
Use any HTTP client capable of plain-text requests. Prometheus scrapers should target
|
||||
the same URL. The endpoint returns data in the standard exposition format produced by
|
||||
`prometheus-client`.
|
||||
|
||||
## Prometheus scrape configuration
|
||||
|
||||
Add a job to your Prometheus server configuration that points to the PotatoMesh
|
||||
instance. This example polls an instance running locally on the default port every 15
|
||||
seconds:
|
||||
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: potatomesh
|
||||
scrape_interval: 15s
|
||||
static_configs:
|
||||
- targets:
|
||||
- localhost:41447
|
||||
```
|
||||
|
||||
If your deployment requires authentication or runs behind a reverse proxy, configure
|
||||
Prometheus to match your network topology (for example by adding basic authentication
|
||||
credentials, custom headers, or TLS settings).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **No per-node metrics appear.** Ensure that `PROM_REPORT_IDS` is set and that the
|
||||
specified nodes exist in the database. Set the value to `*` if you want to export
|
||||
every node during initial validation.
|
||||
- **Metrics look stale after a restart.** Confirm that the ingestor is still posting
|
||||
telemetry. The exporter only reflects data stored in the PotatoMesh database.
|
||||
- **Scrapes time out.** Verify that the Prometheus server can reach the PotatoMesh
|
||||
HTTP port and that no reverse proxy is blocking the `/metrics` path.
|
||||
|
||||
With the endpoint configured, you can build Grafana dashboards or alerting rules to
|
||||
keep track of community mesh health in real time.
|
||||
370
README.md
@@ -1,70 +1,54 @@
|
||||
# potato-mesh
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
a simple meshtastic node dashboard for your local community. here: berlin mediumfast.
|
||||
# 🥔 PotatoMesh
|
||||
|
||||

|
||||
[](https://github.com/l5yth/potato-mesh/actions)
|
||||
[](https://github.com/l5yth/potato-mesh/releases)
|
||||
[](https://codecov.io/gh/l5yth/potato-mesh)
|
||||
[](LICENSE)
|
||||
[](https://github.com/l5yth/potato-mesh/issues)
|
||||
[](https://matrix.to/#/#potatomesh:dod.ngo)
|
||||
|
||||
## status
|
||||
[](https://meshtastic.org)
|
||||
[](https://meshcore.co.uk)
|
||||
|
||||
_in active development._
|
||||
A federated, Meshtastic & Meshcore node dashboard for your local community.
|
||||
_No MQTT clutter, just local LoRa aether._
|
||||
|
||||
what works:
|
||||
* Web dashboard with chat window and map view showing nodes, positions, neighbors,
|
||||
trace routes, telemetry, and messages.
|
||||
* API to POST (authenticated) and to GET nodes, messages, and telemetry.
|
||||
* Shows new node notifications (first seen) and telemetry logs in chat.
|
||||
* Allows searching and filtering for nodes in map and table view.
|
||||
* Federated: _automatically_ froms a federation with other communities running
|
||||
Potato Mesh!
|
||||
* Supports Meshtastic and Meshcore
|
||||
* Supplemental Python ingestor to feed the POST APIs of the Web app with data remotely.
|
||||
* Supports multiple ingestors per instance.
|
||||
* Supports Meshtastic and Meshcore
|
||||
* Matrix bridge that posts Meshtastic messages to a defined matrix channel (no
|
||||
radio required).
|
||||
* Mobile app to _read_ messages on your local aether (no radio required).
|
||||
|
||||
* updating nodes from a locally connected meshtastic device (via serial)
|
||||
* awaiting messages on default channel (0) from a local meshtastic device
|
||||
* storing nodes and messages in a local database (sqlite3)
|
||||
* displaying nodes ordered by last seen in a web app table view
|
||||
* displaying nodes by geographic coordinates on a map layer, coloured by device role
|
||||
* displaying new node notifications and chat messages in default channel in chat box
|
||||
* displaying active node count and filtering nodes by name
|
||||
* exposing nodes and messages to api endpoints
|
||||
Live demo for Berlin: [potatomesh.net](https://potatomesh.net)
|
||||
|
||||
what does not work _(yet):_
|
||||

|
||||
|
||||
* posting nodes and messages to the api endpoints _(wip)_
|
||||
## Web App
|
||||
|
||||
## requirements
|
||||
|
||||
requires a meshtastic node connected (via serial) to gather mesh data and the meshtastic cli.
|
||||
|
||||
requires the meshtastic python api for the database.
|
||||
Requires Ruby for the Sinatra web app and SQLite3 for the app's database.
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -U meshtastic
|
||||
```
|
||||
|
||||
requires latest ruby and ruby gems for the sinatra web app.
|
||||
|
||||
```bash
|
||||
gem install bundler
|
||||
pacman -S ruby sqlite3
|
||||
gem install sinatra sqlite3 rackup puma rspec rack-test rufo prometheus-client
|
||||
cd ./web
|
||||
bundle install
|
||||
```
|
||||
|
||||
### database
|
||||
### Run
|
||||
|
||||
uses python meshtastic library to ingest mesh data into an sqlite3 database locally
|
||||
|
||||
run `mesh.sh` in `data/` to keep updating node records and parsing new incoming messages.
|
||||
|
||||
```bash
|
||||
MESH_SERIAL=/dev/ttyACM0 DEBUG=1 ./mesh.sh
|
||||
[...]
|
||||
[debug] upserted node !849b7154 shortName='7154'
|
||||
[debug] upserted node !ba653ae8 shortName='3ae8'
|
||||
[debug] upserted node !16ced364 shortName='Pat'
|
||||
[debug] stored message from '!9ee71c38' to '^all' ch=0 text='Guten Morgen!'
|
||||
```
|
||||
|
||||
enable debug output with `DEBUG=1`, specify the serial port with `MESH_SERIAL` (default `/dev/ttyACM0`).
|
||||
|
||||
### web app
|
||||
|
||||
uses a ruby sinatra webapp to display data from the sqlite database
|
||||
|
||||
run `app.sh` in `web/` to run the sinatra webserver and check
|
||||
[127.0.0.1:41447](http://127.0.0.1:41447/) for the correct node map.
|
||||
Check out the `app.sh` run script in `./web` directory.
|
||||
|
||||
```bash
|
||||
API_TOKEN="1eb140fd-cab4-40be-b862-41c607762246" ./app.sh
|
||||
@@ -76,17 +60,283 @@ Puma starting in single mode...
|
||||
* Listening on http://127.0.0.1:41447
|
||||
```
|
||||
|
||||
set `API_TOKEN` required for authorizations on the api post-endpoints (wip).
|
||||
Check [127.0.0.1:41447](http://127.0.0.1:41447/) for the development preview
|
||||
of the node map. Set `API_TOKEN` required for authorizations on the API's POST endpoints.
|
||||
|
||||
## api
|
||||
### Production
|
||||
|
||||
the web app contains an api:
|
||||
When promoting the app to production, run the server with the minimum required
|
||||
configuration to ensure secure access and proper routing:
|
||||
|
||||
* GET `/api/nodes?limit=1000` - returns the latest 1000 nodes reported to the app
|
||||
* GET `/api/messages?limit=1000` - returns the latest 1000 messages
|
||||
```bash
|
||||
RACK_ENV="production" \
|
||||
APP_ENV="production" \
|
||||
API_TOKEN="SuperSecureTokenReally" \
|
||||
INSTANCE_DOMAIN="https://potatomesh.net" \
|
||||
MAP_CENTER="53.55,13.42" \
|
||||
exec ruby app.rb -p 41447 -o 0.0.0.0
|
||||
```
|
||||
|
||||
the `POST` apis are _currently being worked on (tm)._
|
||||
* `RACK_ENV` and `APP_ENV` must be set to `production` to enable optimized
|
||||
settings suited for live deployments.
|
||||
* Bind the server to a production port and all interfaces (`-p 41447 -o 0.0.0.0`)
|
||||
so that clients can reach the dashboard over the network.
|
||||
* Provide a strong `API_TOKEN` value to authorize POST requests against the API.
|
||||
* Configure `INSTANCE_DOMAIN` with the public URL of your deployment so vanity
|
||||
links and generated metadata resolve correctly.
|
||||
* Don't forget to set a `MAP_CENTER` to point to your local region.
|
||||
|
||||
## license
|
||||
The web app can be configured with environment variables (defaults shown):
|
||||
|
||||
apache v2.0
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `API_TOKEN` | _required_ | Shared secret that authorizes ingestors and API clients making `POST` requests. |
|
||||
| `INSTANCE_DOMAIN` | _auto-detected_ | Public hostname (optionally with port) used for metadata, federation, and generated API links. |
|
||||
| `SITE_NAME` | `"PotatoMesh Demo"` | Title and header displayed in the UI. |
|
||||
| `CHANNEL` | `"#LongFast"` | Default channel name displayed in the UI. |
|
||||
| `FREQUENCY` | `"915MHz"` | Default frequency description displayed in the UI. |
|
||||
| `CONTACT_LINK` | `"#potatomesh:dod.ngo"` | Chat link or Matrix alias rendered in the footer and overlays. |
|
||||
| `ANNOUNCEMENT` | _unset_ | Optional announcement banner text rendered above the header on every page. |
|
||||
| `MAP_CENTER` | `38.761944,-27.090833` | Latitude and longitude that centre the map on load. |
|
||||
| `MAP_ZOOM` | _unset_ | Fixed Leaflet zoom applied on first load; disables auto-fit when provided. |
|
||||
| `MAX_DISTANCE` | `42` | Maximum distance (km) before node relationships are hidden on the map. |
|
||||
| `DEBUG` | `0` | Set to `1` for verbose logging in the web and ingestor services. |
|
||||
| `ALLOWED_CHANNELS` | _unset_ | Comma-separated channel names the ingestor accepts; when set, all other channels are skipped before hidden filters. |
|
||||
| `HIDDEN_CHANNELS` | _unset_ | Comma-separated channel names the ingestor will ignore when forwarding packets. |
|
||||
| `FEDERATION` | `1` | Set to `1` to announce your instance and crawl peers, or `0` to disable federation. Private mode overrides this. |
|
||||
| `PRIVATE` | `0` | Set to `1` to hide the chat UI, disable message APIs, and exclude hidden clients from public listings. |
|
||||
|
||||
The application derives SEO-friendly document titles, descriptions, and social
|
||||
preview tags from these existing configuration values and reuses the bundled
|
||||
logo for Open Graph and Twitter cards.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
SITE_NAME="PotatoMesh Demo" MAP_CENTER=38.761944,-27.090833 MAP_ZOOM=11 MAX_DISTANCE=42 CONTACT_LINK="#potatomesh:dod.ngo" ./app.sh
|
||||
```
|
||||
|
||||
### Configuration & Storage
|
||||
|
||||
PotatoMesh stores its runtime assets using the XDG base directory specification.
|
||||
When XDG directories are not provided the application falls back
|
||||
to the repository root.
|
||||
|
||||
The key is written to `$XDG_CONFIG_HOME/potato-mesh/keyfile` and the
|
||||
well-known document is staged in
|
||||
`$XDG_CONFIG_HOME/potato-mesh/well-known/potato-mesh`.
|
||||
|
||||
The database can be found in `$XDG_DATA_HOME/potato-mesh`.
|
||||
|
||||
### Custom Pages
|
||||
|
||||
Instance operators can publish static content pages (contact details, mesh
|
||||
protocol information, legal notices, etc.) by placing Markdown files in the
|
||||
`pages/` directory inside `web/`. Each `.md` file automatically becomes a nav
|
||||
entry and a route under `/pages/<slug>`.
|
||||
|
||||
Files are named `<sort-prefix>-<slug>.md` — the numeric prefix controls
|
||||
navigation order and the slug becomes the URL path and nav label:
|
||||
|
||||
| Filename | Nav Label | URL |
|
||||
| ---------------------- | -------------- | ----------------------- |
|
||||
| `1-about.md` | About | `/pages/about` |
|
||||
| `5-rules.md` | Rules | `/pages/rules` |
|
||||
| `9-contact.md` | Contact | `/pages/contact` |
|
||||
| `20-impressum.md` | Impressum | `/pages/impressum` |
|
||||
|
||||
A default `1-about.md` ships with the app. In Docker deployments the directory
|
||||
is exposed as the `potatomesh_pages` volume (mounted at `/app/pages`) so you can
|
||||
add or edit pages without rebuilding the image. The pages directory can also be
|
||||
overridden with the `PAGES_DIR` environment variable.
|
||||
|
||||
### Federation
|
||||
|
||||
PotatoMesh instances can optionally federate by publishing signed metadata and
|
||||
discovering peers. Federation is enabled by default and controlled with the
|
||||
`FEDERATION` environment variable. Set `FEDERATION=1` (default) to announce your
|
||||
instance, respond to remote crawlers, and crawl the wider network. Set
|
||||
`FEDERATION=0` to keep your deployment isolated. Private mode still takes
|
||||
precedence; when `PRIVATE=1`, federation features remain disabled regardless of
|
||||
the `FEDERATION` value.
|
||||
|
||||
When federation is enabled, PotatoMesh automatically refreshes entries from
|
||||
known peers every eight hours to keep the directory current. Instances that
|
||||
stop responding are considered stale and are removed from the web frontend after
|
||||
72 hours, ensuring visitors only see active deployments in the public
|
||||
directory.
|
||||
|
||||
### API
|
||||
|
||||
The web app contains an API:
|
||||
|
||||
* GET `/api/nodes?limit=100` - returns the latest 100 nodes reported to the app
|
||||
* GET `/api/positions?limit=100` - returns the latest 100 position data
|
||||
* GET `/api/messages?limit=100&encrypted=false&since=0` - returns the latest 100 messages newer than the provided unix timestamp (defaults to `since=0` to return full history; disabled when `PRIVATE=1`)
|
||||
* GET `/api/telemetry?limit=100` - returns the latest 100 telemetry data
|
||||
* GET `/api/neighbors?limit=100` - returns the latest 100 neighbor tuples
|
||||
* GET `/api/traces?limit=100` - returns the latest 100 trace-routes caught
|
||||
* GET `/api/instances` - returns known potato-mesh instances in other locations
|
||||
* GET `/api/ingestors` - returns active potato-mesh python ingestors that feed data
|
||||
* GET `/metrics`- metrics for the prometheus endpoint
|
||||
* GET `/version`- information about the potato-mesh instance
|
||||
* POST `/api/nodes` - upserts nodes provided as JSON object mapping node ids to node data (requires `Authorization: Bearer <API_TOKEN>`)
|
||||
* POST `/api/positions` - appends positions provided as a JSON object or array (requires `Authorization: Bearer <API_TOKEN>`)
|
||||
* POST `/api/messages` - appends messages provided as a JSON object or array (requires `Authorization: Bearer <API_TOKEN>`; disabled when `PRIVATE=1`)
|
||||
* POST `/api/telemetry` - appends telemetry provided as a JSON object or array (requires `Authorization: Bearer <API_TOKEN>`)
|
||||
* POST `/api/neighbors` - appends neighbor tuples provided as a JSON object or array (requires `Authorization: Bearer <API_TOKEN>`)
|
||||
* POST `/api/traces` - appends caught traces routes provided as a JSON object or array (requires `Authorization: Bearer <API_TOKEN>`)
|
||||
|
||||
The `API_TOKEN` environment variable must be set to a non-empty value and match the token supplied in the `Authorization` header for `POST` requests.
|
||||
|
||||
### Monitoring
|
||||
|
||||
PotatoMesh ships with a Prometheus exporter mounted at `/metrics`. Consult
|
||||
[`PROMETHEUS.md`](./PROMETHEUS.md) for deployment guidance, metric details, and
|
||||
scrape configuration examples.
|
||||
|
||||
## Python Ingestor
|
||||
|
||||
The web app is not meant to be run locally connected to a Meshtastic node but rather
|
||||
on a remote host without access to a physical Meshtastic device. Therefore, it only
|
||||
accepts data through the API POST endpoints. Benefit is, here _multiple nodes across the
|
||||
community_ can feed the dashboard with data. The web app handles messages and nodes
|
||||
by ID and there will be no duplication.
|
||||
|
||||
For convenience, the directory `./data` contains a Python ingestor. It connects to a
|
||||
Meshtastic node via serial port or to a remote device that exposes the Meshtastic TCP
|
||||
or Bluetooth (BLE) interfaces to gather nodes and messages seen by the node.
|
||||
|
||||
```bash
|
||||
pacman -S python
|
||||
cd ./data
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -U meshtastic
|
||||
```
|
||||
|
||||
It uses the Meshtastic Python library to ingest mesh data and post nodes and messages
|
||||
to the configured potato-mesh instance.
|
||||
|
||||
Check out `mesh.sh` ingestor script in the `./data` directory.
|
||||
|
||||
```bash
|
||||
INSTANCE_DOMAIN=http://127.0.0.1:41447 API_TOKEN=1eb140fd-cab4-40be-b862-41c607762246 CONNECTION=/dev/ttyACM0 DEBUG=1 ./mesh.sh
|
||||
[2025-02-20T12:34:56.789012Z] [potato-mesh] [info] channel=0 context=daemon.main port='41447' target='http://127.0.0.1' Mesh daemon starting
|
||||
[...]
|
||||
[2025-02-20T12:34:57.012345Z] [potato-mesh] [debug] context=handlers.upsert_node node_id=!849b7154 short_name='7154' long_name='7154' Queued node upsert payload
|
||||
[2025-02-20T12:34:57.456789Z] [potato-mesh] [debug] context=handlers.upsert_node node_id=!ba653ae8 short_name='3ae8' long_name='3ae8' Queued node upsert payload
|
||||
[2025-02-20T12:34:58.001122Z] [potato-mesh] [debug] context=handlers.store_packet_dict channel=0 from_id='!9ee71c38' payload='Guten Morgen!' to_id='^all' Queued message payload
|
||||
```
|
||||
|
||||
Run the script with `INSTANCE_DOMAIN` and `API_TOKEN` to keep updating
|
||||
node records and parsing new incoming messages. Enable debug output with `DEBUG=1`,
|
||||
specify the connection target with `CONNECTION` (default `/dev/ttyACM0`) or set it to
|
||||
an IP address (for example `192.168.1.20:4403`) to use the Meshtastic TCP
|
||||
interface. `CONNECTION` also accepts Bluetooth device addresses in MAC format (e.g.,
|
||||
`ED:4D:9E:95:CF:60`) or UUID format for macOS (e.g., `C0AEA92F-045E-9B82-C9A6-A1FD822B3A9E`)
|
||||
and the script attempts a BLE connection if available. To keep
|
||||
ingestion limited, set `ALLOWED_CHANNELS` to a comma-separated whitelist (for
|
||||
example `ALLOWED_CHANNELS="Chat,Ops"`); packets on other channels are discarded.
|
||||
Use `HIDDEN_CHANNELS` to block specific channels from the web UI even when they
|
||||
appear in the allowlist.
|
||||
|
||||
## Nix
|
||||
|
||||
For the dev shell, run:
|
||||
|
||||
```bash
|
||||
nix develop
|
||||
```
|
||||
|
||||
The shell provides Ruby plus the Python ingestor dependencies (including `meshtastic`
|
||||
and `protobuf`). To sanity-check that the ingestor starts, run `python -m data.mesh`
|
||||
with the usual environment variables (`INSTANCE_DOMAIN`, `API_TOKEN`, `CONNECTION`).
|
||||
|
||||
To run the packaged apps directly:
|
||||
|
||||
```bash
|
||||
nix run .#web
|
||||
nix run .#ingestor
|
||||
```
|
||||
|
||||
Minimal NixOS module snippet:
|
||||
|
||||
```nix
|
||||
services.potato-mesh = {
|
||||
enable = true;
|
||||
apiTokenFile = config.sops.secrets.potato-mesh-api-token.path;
|
||||
dataDir = "/var/lib/potato-mesh";
|
||||
port = 41447;
|
||||
instanceDomain = "https://mesh.me";
|
||||
siteName = "Nix Mesh";
|
||||
contactLink = "homeserver.mx";
|
||||
mapCenter = "28.96,-13.56";
|
||||
frequency = "868MHz";
|
||||
ingestor = {
|
||||
enable = true;
|
||||
connection = "192.168.X.Y:4403";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
Docker images are published on GitHub Container Registry for each release.
|
||||
Image names and tags follow the workflow format:
|
||||
`${IMAGE_PREFIX}-${service}-${architecture}:${tag}` (see `.github/workflows/docker.yml`).
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/l5yth/potato-mesh-web-linux-amd64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-web-linux-arm64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-web-linux-armv7:latest
|
||||
|
||||
docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-amd64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-arm64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-armv7:latest
|
||||
|
||||
docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-amd64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-arm64:latest
|
||||
docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-armv7:latest
|
||||
|
||||
# version-pinned examples
|
||||
docker pull ghcr.io/l5yth/potato-mesh-web-linux-amd64:v0.6.0
|
||||
docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-amd64:v0.6.0
|
||||
docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-amd64:v0.6.0
|
||||
```
|
||||
|
||||
Note: `latest` is only published for non-prerelease versions. Pre-release tags
|
||||
such as `-rc`, `-beta`, `-alpha`, or `-dev` are version-tagged only.
|
||||
|
||||
When using Compose, set `POTATOMESH_IMAGE_ARCH` in `docker-compose.yml` (or via
|
||||
environment) so service images resolve to the correct architecture variant and
|
||||
you avoid manual tag mistakes.
|
||||
|
||||
Feel free to run the [configure.sh](./configure.sh) script to set up your
|
||||
environment. See the [Docker guide](DOCKER.md) for more details and custom
|
||||
deployment instructions.
|
||||
|
||||
## Matrix Bridge
|
||||
|
||||
A matrix bridge is currently being worked on. It requests messages from a configured
|
||||
potato-mesh instance and forwards it to a specified matrix channel; see
|
||||
[matrix/README.md](./matrix/README.md).
|
||||
|
||||

|
||||
|
||||
## Mobile App
|
||||
|
||||
A mobile _reader_ app is currently being worked on. Stay tuned for releases and updates.
|
||||
|
||||
## Demos
|
||||
|
||||
Post your nodes and screenshots here:
|
||||
|
||||
* <https://github.com/l5yth/potato-mesh/discussions/258>
|
||||
|
||||
## License
|
||||
|
||||
Apache v2.0, Contact <COM0@l5y.tech>
|
||||
|
||||
Join our community chat to discuss the dashboard or ask for technical support:
|
||||
[#potatomesh:dod.ngo](https://matrix.to/#/#potatomesh:dod.ngo)
|
||||
|
||||
29
app/.gitignore
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
|
||||
# Scaffholding
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
.fvmrc
|
||||
.idea/
|
||||
.metadata
|
||||
linux/
|
||||
macos/
|
||||
potato_mesh_reader.iml
|
||||
pubspec.lock
|
||||
web/
|
||||
windows/
|
||||
# Android/Gradle outputs
|
||||
android/.gradle/
|
||||
android/app/build/
|
||||
|
||||
# iOS/Xcode outputs
|
||||
ios/Pods/
|
||||
ios/.symlinks/
|
||||
ios/Flutter/ephemeral/
|
||||
ios/Flutter/App.framework
|
||||
ios/Flutter/Flutter.framework
|
||||
ios/Flutter/flutter_export_environment.sh
|
||||
ios/Flutter/Generated.xcconfig
|
||||
ios/Runner/GeneratedPluginRegistrant.*
|
||||
16
app/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<!-- Licensed under the Apache License, Version 2.0 (see LICENSE) -->
|
||||
|
||||
# PotatoMesh Mobile
|
||||
|
||||
PotatoMesh Mobile — read-only mesh chat client for Android and iOS.
|
||||
Supports Meshtastic and MeshCore networks.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
cd app
|
||||
flutter create .
|
||||
flutter pub get
|
||||
flutter run
|
||||
```
|
||||
28
app/analysis_options.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
11
app/android/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/.gradle
|
||||
/captures/
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.cxx/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
64
app/android/app/build.gradle.kts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright © 2025-26 l5yth & contributors
|
||||
* 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.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "net.potatomesh.reader"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "net.potatomesh.reader"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||
}
|
||||
7
app/android/app/src/debug/AndroidManifest.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
49
app/android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.potatomesh.reader">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<application
|
||||
android:label="PotatoMesh Reader"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name="net.potatomesh.reader.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright © 2025-26 l5yth & contributors
|
||||
// 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.
|
||||
|
||||
package net.potatomesh.reader
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
BIN
app/android/app/src/main/res/drawable-hdpi/android12splash.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
BIN
app/android/app/src/main/res/drawable-hdpi/splash.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
app/android/app/src/main/res/drawable-mdpi/android12splash.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
BIN
app/android/app/src/main/res/drawable-mdpi/splash.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 39 KiB |
BIN
app/android/app/src/main/res/drawable-v21/background.png
Normal file
|
After Width: | Height: | Size: 69 B |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
BIN
app/android/app/src/main/res/drawable-xhdpi/android12splash.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 18 KiB |
BIN
app/android/app/src/main/res/drawable-xhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
app/android/app/src/main/res/drawable-xxhdpi/android12splash.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 31 KiB |
BIN
app/android/app/src/main/res/drawable-xxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 48 KiB |
BIN
app/android/app/src/main/res/drawable-xxxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
app/android/app/src/main/res/drawable/background.png
Normal file
|
After Width: | Height: | Size: 69 B |
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M 126.00 231.38 C116.24,230.24 108.69,228.55 97.57,225.02 C89.71,222.53 81.61,220.73 74.92,220.01 C56.54,218.03 47.54,215.19 35.90,207.72 C25.90,201.31 16.09,188.73 11.28,176.17 C9.05,170.34 8.73,167.93 8.69,157.00 C8.66,146.56 9.01,143.52 10.83,138.58 C13.71,130.75 16.90,125.44 22.99,118.35 C25.75,115.13 30.06,108.55 32.57,103.72 C39.65,90.08 52.73,77.41 61.66,75.54 C63.80,75.09 65.00,74.16 65.38,72.61 C66.30,68.96 73.33,61.70 79.81,57.70 C83.11,55.66 86.29,54.00 86.90,54.00 C87.50,54.00 91.26,50.90 95.25,47.11 C107.07,35.89 118.95,31.10 131.78,32.42 C139.49,33.21 147.99,37.24 153.00,42.48 C154.93,44.50 160.84,48.38 166.15,51.12 C175.72,56.04 185.00,64.04 185.00,67.35 C185.00,68.84 187.05,70.00 189.69,70.00 C190.52,70.00 193.21,71.35 195.66,73.00 C198.10,74.65 200.30,76.00 200.55,76.00 C201.87,76.00 209.57,85.37 213.05,91.22 C215.39,95.15 221.15,102.01 226.90,107.72 C237.44,118.20 241.06,123.94 244.87,136.29 C252.34,160.53 244.67,187.19 225.29,204.27 C215.26,213.12 206.19,217.02 189.50,219.66 C184.00,220.54 174.32,222.95 168.00,225.04 C152.19,230.25 136.54,232.62 126.00,231.38 ZM 149.23 220.54 C152.93,219.75 160.90,217.52 166.93,215.57 C172.97,213.61 182.16,211.33 187.36,210.50 C192.56,209.66 198.70,208.31 200.99,207.50 C219.04,201.13 232.11,186.69 236.54,168.21 C239.68,155.13 237.23,137.60 230.79,127.15 C229.56,125.14 224.01,118.78 218.45,113.00 C212.70,107.01 206.60,99.49 204.27,95.50 C200.27,88.66 197.03,85.00 192.03,81.65 C188.54,79.32 187.14,79.59 186.36,82.75 C184.35,90.89 178.61,95.54 166.19,99.09 C162.70,100.09 157.74,102.15 155.17,103.68 C142.50,111.19 133.13,113.70 123.94,112.03 C120.95,111.49 114.12,108.78 108.77,106.02 C100.44,101.72 97.99,100.92 91.77,100.48 C81.44,99.74 78.08,99.08 74.05,97.01 C69.74,94.80 66.49,91.44 65.08,87.73 C64.04,84.97 64.02,84.96 60.27,86.48 C54.59,88.78 45.89,98.56 40.58,108.65 C38.01,113.52 33.29,120.79 30.09,124.80 C22.80,133.95 19.57,140.55 17.99,149.58 C14.84,167.46 24.86,188.52 41.92,199.87 C51.75,206.40 57.70,208.37 74.36,210.57 C80.89,211.43 90.12,213.30 94.86,214.73 C115.79,221.03 120.20,221.90 131.50,221.93 C137.55,221.95 145.53,221.32 149.23,220.54 ZM 136.76 102.49 C140.36,101.65 145.79,99.27 149.54,96.90 C153.18,94.60 159.03,92.02 162.79,91.05 C170.97,88.95 173.22,87.80 175.92,84.37 C178.38,81.24 178.67,75.20 176.55,71.10 C174.28,66.71 168.40,62.13 160.26,58.42 C155.62,56.31 150.53,52.93 146.85,49.52 C133.35,37.02 118.65,38.50 101.56,54.08 C97.39,57.87 91.17,62.38 87.74,64.10 C77.86,69.03 73.00,74.56 73.00,80.87 C73.00,88.43 77.15,90.86 91.91,91.95 C102.41,92.73 103.22,92.96 111.55,97.50 C124.46,104.54 126.44,104.93 136.76,102.49 ZM 88.35 189.48 C87.37,186.91 91.59,125.01 92.84,123.76 C94.47,122.13 105.29,121.55 107.91,122.95 C109.31,123.70 113.25,130.52 118.80,141.81 L 127.51 159.50 L 136.00 142.15 C140.68,132.61 145.09,124.17 145.82,123.40 C146.71,122.46 149.41,122.00 154.00,122.00 C161.67,122.00 163.99,123.34 164.02,127.82 C164.03,129.29 164.70,140.18 165.50,152.00 C167.35,179.25 167.41,189.65 165.75,190.21 C165.06,190.44 161.57,190.38 158.00,190.07 L 151.50 189.50 L 150.36 170.00 C149.73,159.27 149.14,150.27 149.06,150.00 C148.98,149.73 145.22,156.70 140.71,165.50 L 132.50 181.50 L 127.50 181.50 L 122.50 181.50 L 114.25 165.08 C107.87,152.38 105.97,149.32 105.88,151.58 C105.82,153.19 105.81,154.81 105.86,155.18 C105.91,155.55 105.48,163.42 104.90,172.67 C104.23,183.39 103.43,189.74 102.68,190.22 C102.03,190.63 98.67,190.98 95.22,190.98 C90.51,191.00 88.79,190.62 88.35,189.48 ZM 61.61 182.42 C60.64,179.90 60.89,178.25 62.48,176.66 C65.63,173.51 69.97,177.37 68.50,182.00 C67.71,184.48 62.52,184.80 61.61,182.42 ZM 216.53 167.38 C215.64,166.50 215.07,165.29 215.26,164.71 C215.85,162.94 218.62,161.64 220.36,162.31 C222.46,163.11 222.50,167.60 220.42,168.39 C218.30,169.21 218.37,169.22 216.53,167.38 ZM 36.04 153.55 C33.39,150.36 37.30,145.34 40.42,147.93 C42.30,149.49 42.47,152.13 40.80,153.80 C39.20,155.40 37.51,155.31 36.04,153.55 ZM 201.16 148.12 C199.41,147.01 200.04,142.99 202.19,141.64 C203.48,140.83 204.37,141.02 205.94,142.45 C208.41,144.68 208.48,145.38 206.43,147.43 C204.67,149.18 203.15,149.38 201.16,148.12 ZM 67.34 137.43 C66.47,135.18 68.24,132.50 70.61,132.50 C73.61,132.50 73.27,138.39 70.25,138.82 C68.83,139.02 67.75,138.50 67.34,137.43 ZM 56.54 116.66 C55.17,115.65 54.88,114.62 55.39,112.59 C55.94,110.38 56.56,109.93 58.68,110.19 C62.53,110.65 63.88,113.37 61.55,115.94 C59.36,118.37 58.96,118.42 56.54,116.66 ZM 186.67 113.33 C185.21,111.88 186.09,108.02 188.12,106.93 C189.87,106.00 190.60,106.15 192.23,107.78 C195.00,110.56 193.82,114.00 190.10,114.00 C188.58,114.00 187.03,113.70 186.67,113.33 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright © 2025-26 l5yth & contributors -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M 126.00 231.38 C116.24,230.24 108.69,228.55 97.57,225.02 C89.71,222.53 81.61,220.73 74.92,220.01 C56.54,218.03 47.54,215.19 35.90,207.72 C25.90,201.31 16.09,188.73 11.28,176.17 C9.05,170.34 8.73,167.93 8.69,157.00 C8.66,146.56 9.01,143.52 10.83,138.58 C13.71,130.75 16.90,125.44 22.99,118.35 C25.75,115.13 30.06,108.55 32.57,103.72 C39.65,90.08 52.73,77.41 61.66,75.54 C63.80,75.09 65.00,74.16 65.38,72.61 C66.30,68.96 73.33,61.70 79.81,57.70 C83.11,55.66 86.29,54.00 86.90,54.00 C87.50,54.00 91.26,50.90 95.25,47.11 C107.07,35.89 118.95,31.10 131.78,32.42 C139.49,33.21 147.99,37.24 153.00,42.48 C154.93,44.50 160.84,48.38 166.15,51.12 C175.72,56.04 185.00,64.04 185.00,67.35 C185.00,68.84 187.05,70.00 189.69,70.00 C190.52,70.00 193.21,71.35 195.66,73.00 C198.10,74.65 200.30,76.00 200.55,76.00 C201.87,76.00 209.57,85.37 213.05,91.22 C215.39,95.15 221.15,102.01 226.90,107.72 C237.44,118.20 241.06,123.94 244.87,136.29 C252.34,160.53 244.67,187.19 225.29,204.27 C215.26,213.12 206.19,217.02 189.50,219.66 C184.00,220.54 174.32,222.95 168.00,225.04 C152.19,230.25 136.54,232.62 126.00,231.38 ZM 149.23 220.54 C152.93,219.75 160.90,217.52 166.93,215.57 C172.97,213.61 182.16,211.33 187.36,210.50 C192.56,209.66 198.70,208.31 200.99,207.50 C219.04,201.13 232.11,186.69 236.54,168.21 C239.68,155.13 237.23,137.60 230.79,127.15 C229.56,125.14 224.01,118.78 218.45,113.00 C212.70,107.01 206.60,99.49 204.27,95.50 C200.27,88.66 197.03,85.00 192.03,81.65 C188.54,79.32 187.14,79.59 186.36,82.75 C184.35,90.89 178.61,95.54 166.19,99.09 C162.70,100.09 157.74,102.15 155.17,103.68 C142.50,111.19 133.13,113.70 123.94,112.03 C120.95,111.49 114.12,108.78 108.77,106.02 C100.44,101.72 97.99,100.92 91.77,100.48 C81.44,99.74 78.08,99.08 74.05,97.01 C69.74,94.80 66.49,91.44 65.08,87.73 C64.04,84.97 64.02,84.96 60.27,86.48 C54.59,88.78 45.89,98.56 40.58,108.65 C38.01,113.52 33.29,120.79 30.09,124.80 C22.80,133.95 19.57,140.55 17.99,149.58 C14.84,167.46 24.86,188.52 41.92,199.87 C51.75,206.40 57.70,208.37 74.36,210.57 C80.89,211.43 90.12,213.30 94.86,214.73 C115.79,221.03 120.20,221.90 131.50,221.93 C137.55,221.95 145.53,221.32 149.23,220.54 ZM 136.76 102.49 C140.36,101.65 145.79,99.27 149.54,96.90 C153.18,94.60 159.03,92.02 162.79,91.05 C170.97,88.95 173.22,87.80 175.92,84.37 C178.38,81.24 178.67,75.20 176.55,71.10 C174.28,66.71 168.40,62.13 160.26,58.42 C155.62,56.31 150.53,52.93 146.85,49.52 C133.35,37.02 118.65,38.50 101.56,54.08 C97.39,57.87 91.17,62.38 87.74,64.10 C77.86,69.03 73.00,74.56 73.00,80.87 C73.00,88.43 77.15,90.86 91.91,91.95 C102.41,92.73 103.22,92.96 111.55,97.50 C124.46,104.54 126.44,104.93 136.76,102.49 ZM 88.35 189.48 C87.37,186.91 91.59,125.01 92.84,123.76 C94.47,122.13 105.29,121.55 107.91,122.95 C109.31,123.70 113.25,130.52 118.80,141.81 L 127.51 159.50 L 136.00 142.15 C140.68,132.61 145.09,124.17 145.82,123.40 C146.71,122.46 149.41,122.00 154.00,122.00 C161.67,122.00 163.99,123.34 164.02,127.82 C164.03,129.29 164.70,140.18 165.50,152.00 C167.35,179.25 167.41,189.65 165.75,190.21 C165.06,190.44 161.57,190.38 158.00,190.07 L 151.50 189.50 L 150.36 170.00 C149.73,159.27 149.14,150.27 149.06,150.00 C148.98,149.73 145.22,156.70 140.71,165.50 L 132.50 181.50 L 127.50 181.50 L 122.50 181.50 L 114.25 165.08 C107.87,152.38 105.97,149.32 105.88,151.58 C105.82,153.19 105.81,154.81 105.86,155.18 C105.91,155.55 105.48,163.42 104.90,172.67 C104.23,183.39 103.43,189.74 102.68,190.22 C102.03,190.63 98.67,190.98 95.22,190.98 C90.51,191.00 88.79,190.62 88.35,189.48 ZM 61.61 182.42 C60.64,179.90 60.89,178.25 62.48,176.66 C65.63,173.51 69.97,177.37 68.50,182.00 C67.71,184.48 62.52,184.80 61.61,182.42 ZM 216.53 167.38 C215.64,166.50 215.07,165.29 215.26,164.71 C215.85,162.94 218.62,161.64 220.36,162.31 C222.46,163.11 222.50,167.60 220.42,168.39 C218.30,169.21 218.37,169.22 216.53,167.38 ZM 36.04 153.55 C33.39,150.36 37.30,145.34 40.42,147.93 C42.30,149.49 42.47,152.13 40.80,153.80 C39.20,155.40 37.51,155.31 36.04,153.55 ZM 201.16 148.12 C199.41,147.01 200.04,142.99 202.19,141.64 C203.48,140.83 204.37,141.02 205.94,142.45 C208.41,144.68 208.48,145.38 206.43,147.43 C204.67,149.18 203.15,149.38 201.16,148.12 ZM 67.34 137.43 C66.47,135.18 68.24,132.50 70.61,132.50 C73.61,132.50 73.27,138.39 70.25,138.82 C68.83,139.02 67.75,138.50 67.34,137.43 ZM 56.54 116.66 C55.17,115.65 54.88,114.62 55.39,112.59 C55.94,110.38 56.56,109.93 58.68,110.19 C62.53,110.65 63.88,113.37 61.55,115.94 C59.36,118.37 58.96,118.42 56.54,116.66 ZM 186.67 113.33 C185.21,111.88 186.09,108.02 188.12,106.93 C189.87,106.00 190.60,106.15 192.23,107.78 C195.00,110.56 193.82,114.00 190.10,114.00 C188.58,114.00 187.03,113.70 186.67,113.33 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="16%" />
|
||||
</foreground>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||
</adaptive-icon>
|
||||
BIN
app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
21
app/android/app/src/main/res/values-night-v31/styles.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#111417</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
22
app/android/app/src/main/res/values-night/styles.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
21
app/android/app/src/main/res/values-v31/styles.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:windowSplashScreenBackground">#111417</item>
|
||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/android12splash</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
4
app/android/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#111417</color>
|
||||
</resources>
|
||||
22
app/android/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
7
app/android/app/src/profile/AndroidManifest.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
39
app/android/build.gradle.kts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright © 2025-26 l5yth & contributors
|
||||
* 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.
|
||||
*/
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory =
|
||||
rootProject.layout.buildDirectory
|
||||
.dir("../../build")
|
||||
.get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
2
app/android/gradle.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
BIN
app/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
app/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
||||
160
app/android/gradlew
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
app/android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
29
app/android/potato_mesh_reader_android.iml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" />
|
||||
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" />
|
||||
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/kotlin" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
41
app/android/settings.gradle.kts
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright © 2025-26 l5yth & contributors
|
||||
* 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.
|
||||
*/
|
||||
|
||||
pluginManagement {
|
||||
val flutterSdkPath =
|
||||
run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.11.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
BIN
app/assets/icon-launcher.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
app/assets/icon-splash.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
app/assets/icon.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
5
app/assets/monochrom.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<g>
|
||||
<path d="M 126.00 231.38 C116.24,230.24 108.69,228.55 97.57,225.02 C89.71,222.53 81.61,220.73 74.92,220.01 C56.54,218.03 47.54,215.19 35.90,207.72 C25.90,201.31 16.09,188.73 11.28,176.17 C9.05,170.34 8.73,167.93 8.69,157.00 C8.66,146.56 9.01,143.52 10.83,138.58 C13.71,130.75 16.90,125.44 22.99,118.35 C25.75,115.13 30.06,108.55 32.57,103.72 C39.65,90.08 52.73,77.41 61.66,75.54 C63.80,75.09 65.00,74.16 65.38,72.61 C66.30,68.96 73.33,61.70 79.81,57.70 C83.11,55.66 86.29,54.00 86.90,54.00 C87.50,54.00 91.26,50.90 95.25,47.11 C107.07,35.89 118.95,31.10 131.78,32.42 C139.49,33.21 147.99,37.24 153.00,42.48 C154.93,44.50 160.84,48.38 166.15,51.12 C175.72,56.04 185.00,64.04 185.00,67.35 C185.00,68.84 187.05,70.00 189.69,70.00 C190.52,70.00 193.21,71.35 195.66,73.00 C198.10,74.65 200.30,76.00 200.55,76.00 C201.87,76.00 209.57,85.37 213.05,91.22 C215.39,95.15 221.15,102.01 226.90,107.72 C237.44,118.20 241.06,123.94 244.87,136.29 C252.34,160.53 244.67,187.19 225.29,204.27 C215.26,213.12 206.19,217.02 189.50,219.66 C184.00,220.54 174.32,222.95 168.00,225.04 C152.19,230.25 136.54,232.62 126.00,231.38 ZM 149.23 220.54 C152.93,219.75 160.90,217.52 166.93,215.57 C172.97,213.61 182.16,211.33 187.36,210.50 C192.56,209.66 198.70,208.31 200.99,207.50 C219.04,201.13 232.11,186.69 236.54,168.21 C239.68,155.13 237.23,137.60 230.79,127.15 C229.56,125.14 224.01,118.78 218.45,113.00 C212.70,107.01 206.60,99.49 204.27,95.50 C200.27,88.66 197.03,85.00 192.03,81.65 C188.54,79.32 187.14,79.59 186.36,82.75 C184.35,90.89 178.61,95.54 166.19,99.09 C162.70,100.09 157.74,102.15 155.17,103.68 C142.50,111.19 133.13,113.70 123.94,112.03 C120.95,111.49 114.12,108.78 108.77,106.02 C100.44,101.72 97.99,100.92 91.77,100.48 C81.44,99.74 78.08,99.08 74.05,97.01 C69.74,94.80 66.49,91.44 65.08,87.73 C64.04,84.97 64.02,84.96 60.27,86.48 C54.59,88.78 45.89,98.56 40.58,108.65 C38.01,113.52 33.29,120.79 30.09,124.80 C22.80,133.95 19.57,140.55 17.99,149.58 C14.84,167.46 24.86,188.52 41.92,199.87 C51.75,206.40 57.70,208.37 74.36,210.57 C80.89,211.43 90.12,213.30 94.86,214.73 C115.79,221.03 120.20,221.90 131.50,221.93 C137.55,221.95 145.53,221.32 149.23,220.54 ZM 136.76 102.49 C140.36,101.65 145.79,99.27 149.54,96.90 C153.18,94.60 159.03,92.02 162.79,91.05 C170.97,88.95 173.22,87.80 175.92,84.37 C178.38,81.24 178.67,75.20 176.55,71.10 C174.28,66.71 168.40,62.13 160.26,58.42 C155.62,56.31 150.53,52.93 146.85,49.52 C133.35,37.02 118.65,38.50 101.56,54.08 C97.39,57.87 91.17,62.38 87.74,64.10 C77.86,69.03 73.00,74.56 73.00,80.87 C73.00,88.43 77.15,90.86 91.91,91.95 C102.41,92.73 103.22,92.96 111.55,97.50 C124.46,104.54 126.44,104.93 136.76,102.49 ZM 88.35 189.48 C87.37,186.91 91.59,125.01 92.84,123.76 C94.47,122.13 105.29,121.55 107.91,122.95 C109.31,123.70 113.25,130.52 118.80,141.81 L 127.51 159.50 L 136.00 142.15 C140.68,132.61 145.09,124.17 145.82,123.40 C146.71,122.46 149.41,122.00 154.00,122.00 C161.67,122.00 163.99,123.34 164.02,127.82 C164.03,129.29 164.70,140.18 165.50,152.00 C167.35,179.25 167.41,189.65 165.75,190.21 C165.06,190.44 161.57,190.38 158.00,190.07 L 151.50 189.50 L 150.36 170.00 C149.73,159.27 149.14,150.27 149.06,150.00 C148.98,149.73 145.22,156.70 140.71,165.50 L 132.50 181.50 L 127.50 181.50 L 122.50 181.50 L 114.25 165.08 C107.87,152.38 105.97,149.32 105.88,151.58 C105.82,153.19 105.81,154.81 105.86,155.18 C105.91,155.55 105.48,163.42 104.90,172.67 C104.23,183.39 103.43,189.74 102.68,190.22 C102.03,190.63 98.67,190.98 95.22,190.98 C90.51,191.00 88.79,190.62 88.35,189.48 ZM 61.61 182.42 C60.64,179.90 60.89,178.25 62.48,176.66 C65.63,173.51 69.97,177.37 68.50,182.00 C67.71,184.48 62.52,184.80 61.61,182.42 ZM 216.53 167.38 C215.64,166.50 215.07,165.29 215.26,164.71 C215.85,162.94 218.62,161.64 220.36,162.31 C222.46,163.11 222.50,167.60 220.42,168.39 C218.30,169.21 218.37,169.22 216.53,167.38 ZM 36.04 153.55 C33.39,150.36 37.30,145.34 40.42,147.93 C42.30,149.49 42.47,152.13 40.80,153.80 C39.20,155.40 37.51,155.31 36.04,153.55 ZM 201.16 148.12 C199.41,147.01 200.04,142.99 202.19,141.64 C203.48,140.83 204.37,141.02 205.94,142.45 C208.41,144.68 208.48,145.38 206.43,147.43 C204.67,149.18 203.15,149.38 201.16,148.12 ZM 67.34 137.43 C66.47,135.18 68.24,132.50 70.61,132.50 C73.61,132.50 73.27,138.39 70.25,138.82 C68.83,139.02 67.75,138.50 67.34,137.43 ZM 56.54 116.66 C55.17,115.65 54.88,114.62 55.39,112.59 C55.94,110.38 56.56,109.93 58.68,110.19 C62.53,110.65 63.88,113.37 61.55,115.94 C59.36,118.37 58.96,118.42 56.54,116.66 ZM 186.67 113.33 C185.21,111.88 186.09,108.02 188.12,106.93 C189.87,106.00 190.60,106.15 192.23,107.78 C195.00,110.56 193.82,114.00 190.10,114.00 C188.58,114.00 187.03,113.70 186.67,113.33 Z" fill="rgba(0,0,0,1)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
352
app/assets/potatomesh-logo.svg
Normal file
|
After Width: | Height: | Size: 65 KiB |
27
app/debug.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
# 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.
|
||||
|
||||
export GIT_TAG="$(git describe --tags --abbrev=0)"
|
||||
export GIT_COMMITS="$(git rev-list --count ${GIT_TAG}..HEAD)"
|
||||
export GIT_SHA="$(git rev-parse --short=9 HEAD)"
|
||||
export GIT_DIRTY="$(git diff --quiet --ignore-submodules HEAD || echo true || echo false)"
|
||||
flutter clean
|
||||
flutter pub get
|
||||
flutter run \
|
||||
--dart-define=GIT_TAG="${GIT_TAG}" \
|
||||
--dart-define=GIT_COMMITS="${GIT_COMMITS}" \
|
||||
--dart-define=GIT_SHA="${GIT_SHA}" \
|
||||
--dart-define=GIT_DIRTY="${GIT_DIRTY}" \
|
||||
--device-id 38151FDJH00D4C
|
||||
34
app/ios/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
**/dgph
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/ephemeral/
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
26
app/ios/Flutter/AppFrameworkInfo.plist
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.6.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>14.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
2
app/ios/Flutter/Debug.xcconfig
Normal file
@@ -0,0 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
2
app/ios/Flutter/Release.xcconfig
Normal file
@@ -0,0 +1,2 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
56
app/ios/Podfile
Normal file
@@ -0,0 +1,56 @@
|
||||
# Copyright © 2025-26 l5yth & contributors
|
||||
#
|
||||
# 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.
|
||||
|
||||
platform :ios, "14.0"
|
||||
|
||||
ENV["COCOAPODS_DISABLE_STATS"] = "true"
|
||||
|
||||
project "Runner", {
|
||||
"Debug" => :debug,
|
||||
"Profile" => :release,
|
||||
"Release" => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join("..", "Flutter", "Generated.xcconfig"), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Run flutter pub get and try again."
|
||||
end
|
||||
|
||||
require File.expand_path(File.join("packages", "flutter_tools", "bin", "podhelper"), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target "Runner" do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = "14.0"
|
||||
end
|
||||
end
|
||||
end
|
||||
616
app/ios/Runner.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,616 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.potatomesh.reader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
7
app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
101
app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||
BuildableName = "RunnerTests.xctest"
|
||||
BlueprintName = "RunnerTests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
7
app/ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
26
app/ios/Runner/AppDelegate.swift
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright © 2025-26 l5yth & contributors
|
||||
// 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.
|
||||
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
|
||||
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 889 B |
|
After Width: | Height: | Size: 2.1 KiB |