feat: network module (#1905)
|
@ -0,0 +1,75 @@
|
|||
name: Update Firmware Releases List
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 * * * *' # Run every hour
|
||||
workflow_dispatch: # Allow manual triggering
|
||||
|
||||
jobs:
|
||||
update-hardware-list:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Fetch latest firmware releases data
|
||||
id: fetch-data
|
||||
run: |
|
||||
# Define variables for file paths
|
||||
firmware_releases_json="app/src/main/assets/firmware_releases.json"
|
||||
new_firmware_releases_json="/tmp/new_firmware_releases.json"
|
||||
|
||||
# Fetch data from API
|
||||
curl -s --fail https://api.meshtastic.org/github/firmware/list > "$new_firmware_releases_json"
|
||||
|
||||
# Ensure the output is valid JSON
|
||||
if ! jq empty "$new_firmware_releases_json" 2>/dev/null; then
|
||||
echo "::error::API returned invalid JSON data"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if "$firmware_releases_json" exists
|
||||
if [ -f "$firmware_releases_json" ]; then
|
||||
# Format both files for consistent comparison
|
||||
jq --sort-keys . "$new_firmware_releases_json" > /tmp/new-formatted.json
|
||||
jq --sort-keys . "$firmware_releases_json" > /tmp/existing-formatted.json
|
||||
|
||||
# Compare files
|
||||
if cmp -s /tmp/new-formatted.json /tmp/existing-formatted.json; then
|
||||
echo "No changes detected in hardware list"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Changes detected in hardware list"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "firmware_releases.json doesn't exist yet"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Copy new data to destination
|
||||
cp "$new_firmware_releases_json" "$firmware_releases_json"
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.fetch-data.outputs.has_changes == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: "chore: update firmware releases list from Meshtastic API"
|
||||
title: "chore: update firmware releases list from Meshtastic API"
|
||||
body: |
|
||||
This PR updates the firmware releases list with the latest data from the Meshtastic API.
|
||||
|
||||
This PR was automatically generated by the update-hardware-list workflow.
|
||||
branch: update-hardware-list
|
||||
base: master
|
||||
delete-branch: true
|
|
@ -144,7 +144,7 @@ androidComponents {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation project(":network")
|
||||
implementation(fileTree(dir: 'libs', include: ['*.jar']))
|
||||
|
||||
// Bundles
|
||||
|
@ -159,6 +159,7 @@ dependencies {
|
|||
implementation(libs.bundles.hilt)
|
||||
implementation(libs.bundles.protobuf)
|
||||
implementation(libs.bundles.coil)
|
||||
|
||||
//OSM
|
||||
implementation(libs.bundles.osm)
|
||||
implementation(libs.osmdroid.geopackage){ exclude group: "com.j256.ormlite" }
|
||||
|
|
|
@ -0,0 +1,695 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 17,
|
||||
"identityHash": "6f25f17fe4f83769489c264d4dae0398",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "my_node",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`myNodeNum` INTEGER NOT NULL, `model` TEXT, `firmwareVersion` TEXT, `couldUpdate` INTEGER NOT NULL, `shouldUpdate` INTEGER NOT NULL, `currentPacketId` INTEGER NOT NULL, `messageTimeoutMsec` INTEGER NOT NULL, `minAppVersion` INTEGER NOT NULL, `maxChannels` INTEGER NOT NULL, `hasWifi` INTEGER NOT NULL, `deviceId` TEXT, PRIMARY KEY(`myNodeNum`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "myNodeNum",
|
||||
"columnName": "myNodeNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "model",
|
||||
"columnName": "model",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "firmwareVersion",
|
||||
"columnName": "firmwareVersion",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "couldUpdate",
|
||||
"columnName": "couldUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "shouldUpdate",
|
||||
"columnName": "shouldUpdate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "currentPacketId",
|
||||
"columnName": "currentPacketId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "messageTimeoutMsec",
|
||||
"columnName": "messageTimeoutMsec",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "minAppVersion",
|
||||
"columnName": "minAppVersion",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxChannels",
|
||||
"columnName": "maxChannels",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasWifi",
|
||||
"columnName": "hasWifi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceId",
|
||||
"columnName": "deviceId",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"myNodeNum"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "nodes",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`num` INTEGER NOT NULL, `user` BLOB NOT NULL, `long_name` TEXT, `short_name` TEXT, `position` BLOB NOT NULL, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `snr` REAL NOT NULL, `rssi` INTEGER NOT NULL, `last_heard` INTEGER NOT NULL, `device_metrics` BLOB NOT NULL, `channel` INTEGER NOT NULL, `via_mqtt` INTEGER NOT NULL, `hops_away` INTEGER NOT NULL, `is_favorite` INTEGER NOT NULL, `is_ignored` INTEGER NOT NULL DEFAULT 0, `environment_metrics` BLOB NOT NULL, `power_metrics` BLOB NOT NULL, `paxcounter` BLOB NOT NULL, PRIMARY KEY(`num`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "num",
|
||||
"columnName": "num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "user",
|
||||
"columnName": "user",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longName",
|
||||
"columnName": "long_name",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "shortName",
|
||||
"columnName": "short_name",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "latitude",
|
||||
"columnName": "latitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "longitude",
|
||||
"columnName": "longitude",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "snr",
|
||||
"columnName": "snr",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "rssi",
|
||||
"columnName": "rssi",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastHeard",
|
||||
"columnName": "last_heard",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceTelemetry",
|
||||
"columnName": "device_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "channel",
|
||||
"columnName": "channel",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "viaMqtt",
|
||||
"columnName": "via_mqtt",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hopsAway",
|
||||
"columnName": "hops_away",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isFavorite",
|
||||
"columnName": "is_favorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isIgnored",
|
||||
"columnName": "is_ignored",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "environmentTelemetry",
|
||||
"columnName": "environment_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "powerTelemetry",
|
||||
"columnName": "power_metrics",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "paxcounter",
|
||||
"columnName": "paxcounter",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"num"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "packet",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `myNodeNum` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL, `contact_key` TEXT NOT NULL, `received_time` INTEGER NOT NULL, `read` INTEGER NOT NULL DEFAULT 1, `data` TEXT NOT NULL, `packet_id` INTEGER NOT NULL DEFAULT 0, `routing_error` INTEGER NOT NULL DEFAULT -1, `reply_id` INTEGER NOT NULL DEFAULT 0)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "myNodeNum",
|
||||
"columnName": "myNodeNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "port_num",
|
||||
"columnName": "port_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "contact_key",
|
||||
"columnName": "contact_key",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "received_time",
|
||||
"columnName": "received_time",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "read",
|
||||
"columnName": "read",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "1"
|
||||
},
|
||||
{
|
||||
"fieldPath": "data",
|
||||
"columnName": "data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "packetId",
|
||||
"columnName": "packet_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "routingError",
|
||||
"columnName": "routing_error",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "-1"
|
||||
},
|
||||
{
|
||||
"fieldPath": "replyId",
|
||||
"columnName": "reply_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_packet_myNodeNum",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"myNodeNum"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_myNodeNum` ON `${TABLE_NAME}` (`myNodeNum`)"
|
||||
},
|
||||
{
|
||||
"name": "index_packet_port_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"port_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||
},
|
||||
{
|
||||
"name": "index_packet_contact_key",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"contact_key"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_packet_contact_key` ON `${TABLE_NAME}` (`contact_key`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "contact_settings",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`contact_key` TEXT NOT NULL, `muteUntil` INTEGER NOT NULL, PRIMARY KEY(`contact_key`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "contact_key",
|
||||
"columnName": "contact_key",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "muteUntil",
|
||||
"columnName": "muteUntil",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"contact_key"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "log",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `type` TEXT NOT NULL, `received_date` INTEGER NOT NULL, `message` TEXT NOT NULL, `from_num` INTEGER NOT NULL DEFAULT 0, `port_num` INTEGER NOT NULL DEFAULT 0, `from_radio` BLOB NOT NULL DEFAULT x'', PRIMARY KEY(`uuid`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "message_type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "received_date",
|
||||
"columnName": "received_date",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "raw_message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "fromNum",
|
||||
"columnName": "from_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "portNum",
|
||||
"columnName": "port_num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "fromRadio",
|
||||
"columnName": "from_radio",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true,
|
||||
"defaultValue": "x''"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_log_from_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"from_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_from_num` ON `${TABLE_NAME}` (`from_num`)"
|
||||
},
|
||||
{
|
||||
"name": "index_log_port_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"port_num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_log_port_num` ON `${TABLE_NAME}` (`port_num`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "quick_chat",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `message` TEXT NOT NULL, `mode` TEXT NOT NULL, `position` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "mode",
|
||||
"columnName": "mode",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "reactions",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`reply_id` INTEGER NOT NULL, `user_id` TEXT NOT NULL, `emoji` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`reply_id`, `user_id`, `emoji`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "replyId",
|
||||
"columnName": "reply_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "userId",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "emoji",
|
||||
"columnName": "emoji",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timestamp",
|
||||
"columnName": "timestamp",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"reply_id",
|
||||
"user_id",
|
||||
"emoji"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_reactions_reply_id",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"reply_id"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_reactions_reply_id` ON `${TABLE_NAME}` (`reply_id`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "metadata",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`num` INTEGER NOT NULL, `proto` BLOB NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`num`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "num",
|
||||
"columnName": "num",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "proto",
|
||||
"columnName": "proto",
|
||||
"affinity": "BLOB",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "timestamp",
|
||||
"columnName": "timestamp",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"num"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_metadata_num",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"num"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_metadata_num` ON `${TABLE_NAME}` (`num`)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "device_hardware",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`actively_supported` INTEGER NOT NULL, `architecture` TEXT NOT NULL, `display_name` TEXT NOT NULL, `has_ink_hud` INTEGER, `has_mui` INTEGER, `hwModel` INTEGER NOT NULL, `hw_model_slug` TEXT NOT NULL, `images` TEXT, `last_updated` INTEGER NOT NULL, `partition_scheme` TEXT, `platformio_target` TEXT NOT NULL, `requires_dfu` INTEGER, `support_level` INTEGER, `tags` TEXT, PRIMARY KEY(`hwModel`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "activelySupported",
|
||||
"columnName": "actively_supported",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "architecture",
|
||||
"columnName": "architecture",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "displayName",
|
||||
"columnName": "display_name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasInkHud",
|
||||
"columnName": "has_ink_hud",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasMui",
|
||||
"columnName": "has_mui",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "hwModel",
|
||||
"columnName": "hwModel",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "hwModelSlug",
|
||||
"columnName": "hw_model_slug",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "images",
|
||||
"columnName": "images",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdated",
|
||||
"columnName": "last_updated",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "partitionScheme",
|
||||
"columnName": "partition_scheme",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "platformioTarget",
|
||||
"columnName": "platformio_target",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "requiresDfu",
|
||||
"columnName": "requires_dfu",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "supportLevel",
|
||||
"columnName": "support_level",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"hwModel"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tableName": "firmware_release",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `page_url` TEXT NOT NULL, `release_notes` TEXT NOT NULL, `title` TEXT NOT NULL, `zip_url` TEXT NOT NULL, `last_updated` INTEGER NOT NULL, `release_type` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pageUrl",
|
||||
"columnName": "page_url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "releaseNotes",
|
||||
"columnName": "release_notes",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "zipUrl",
|
||||
"columnName": "zip_url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdated",
|
||||
"columnName": "last_updated",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "releaseType",
|
||||
"columnName": "release_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6f25f17fe4f83769489c264d4dae0398')"
|
||||
]
|
||||
}
|
||||
}
|
Przed Szerokość: | Wysokość: | Rozmiar: 89 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 62 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="795.27 277.13 409.46 1319.35"><defs><style>.cls-1{fill:#353535;}.cls-2{fill:#1e1e1d;}.cls-3{fill:#b1a368;}.cls-10,.cls-11,.cls-4,.cls-6,.cls-8,.cls-9{fill:none;}.cls-4,.cls-6{stroke:#050606;}.cls-10,.cls-11,.cls-4,.cls-6,.cls-8{stroke-miterlimit:10;}.cls-4{stroke-width:2.41px;}.cls-5{fill:#30c2db;}.cls-6{stroke-width:3.91px;}.cls-7{fill:#dcf0f2;}.cls-10,.cls-11,.cls-8{stroke:#dcf0f2;}.cls-8{stroke-width:1.81px;}.cls-9{stroke:#17afbf;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.23px;}.cls-10{stroke-width:1.78px;}.cls-11{stroke-width:1.81px;}</style></defs><g id="Layer_7" data-name="Layer 7"><path class="cls-1" d="M915.62,278.34h22.61a35,35,0,0,1,35,35V715.74a0,0,0,0,1,0,0H880.6a0,0,0,0,1,0,0V313.36A35,35,0,0,1,915.62,278.34Z"></path><rect class="cls-2" x="880.6" y="340.15" width="92.65" height="7.54"></rect><rect class="cls-2" x="880.6" y="356.68" width="92.65" height="7.54"></rect><rect class="cls-3" x="885.8" y="844.3" width="84.14" height="19.02"></rect><rect class="cls-3" x="880.6" y="819.07" width="92.65" height="25.23"></rect><rect class="cls-3" x="885.8" y="790.65" width="84.14" height="28.41"></rect><rect class="cls-3" x="880.6" y="723.02" width="92.65" height="67.63"></rect><rect class="cls-3" x="885.8" y="715.74" width="84.14" height="7.28"></rect><rect class="cls-4" x="885.8" y="844.3" width="84.14" height="19.02"></rect><rect class="cls-4" x="880.6" y="819.07" width="92.65" height="25.23"></rect><rect class="cls-4" x="885.8" y="790.65" width="84.14" height="28.41"></rect><rect class="cls-4" x="880.6" y="723.02" width="92.65" height="67.63"></rect><rect class="cls-4" x="885.8" y="715.74" width="84.14" height="7.28"></rect><path class="cls-4" d="M915.62,278.34h22.61a35,35,0,0,1,35,35V715.74a0,0,0,0,1,0,0H880.6a0,0,0,0,1,0,0V313.36A35,35,0,0,1,915.62,278.34Z"></path><rect class="cls-4" x="880.6" y="340.15" width="92.65" height="7.54"></rect><rect class="cls-4" x="880.6" y="356.68" width="92.65" height="7.54"></rect><rect class="cls-5" x="796.48" y="856.3" width="407.05" height="738.98" rx="47.74"></rect><rect class="cls-1" x="900.05" y="973.19" width="202.03" height="354.65" rx="16.4"></rect><rect class="cls-6" x="900.05" y="973.19" width="202.03" height="354.65" rx="16.4"></rect><rect class="cls-7" x="871.51" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-7" x="1070.16" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-4" x="871.51" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><rect class="cls-4" x="1070.16" y="890.41" width="55.42" height="31.12" rx="15.56"></rect><circle class="cls-8" cx="841.7" cy="1537.01" r="16.25"></circle><circle class="cls-8" cx="841.7" cy="913.26" r="16.25"></circle><circle class="cls-8" cx="1157.32" cy="913.26" r="16.25"></circle><circle class="cls-8" cx="1157.32" cy="1504.51" r="16.25"></circle><line class="cls-9" x1="942.51" y1="1592.42" x2="942.51" y2="1381.55"></line><line class="cls-9" x1="966.52" y1="1592.42" x2="966.52" y2="1381.55"></line><line class="cls-9" x1="990.57" y1="1592.42" x2="990.57" y2="1381.55"></line><line class="cls-9" x1="1014.59" y1="1592.42" x2="1014.59" y2="1381.55"></line><line class="cls-9" x1="1038.63" y1="1592.42" x2="1038.63" y2="1381.55"></line><line class="cls-9" x1="1062.65" y1="1592.42" x2="1062.65" y2="1381.55"></line><rect class="cls-4" x="796.48" y="856.3" width="407.05" height="738.98" rx="47.74"></rect><path class="cls-10" d="M1040.1,947.74H960.65A13.93,13.93,0,0,1,947,936.64l-10.23-49.2a13.93,13.93,0,0,1,13.64-16.77h97.72a13.93,13.93,0,0,1,13.75,16.18l-8,49.2A13.94,13.94,0,0,1,1040.1,947.74Z"></path><rect class="cls-11" x="816.35" y="870.67" width="365.51" height="703.12" rx="32.37"></rect><rect class="cls-11" x="888.77" y="963.84" width="223.2" height="374.66" rx="25.21"></rect></g></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 3.8 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 8.8 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="404.68 390.65 1217.15 959.26"><defs><style>.cls-1{fill:#dfeaf7;}.cls-2{fill:#17907f;}.cls-3{fill:#2b2b2b;}.cls-4,.cls-5{fill:none;stroke:#050606;stroke-miterlimit:10;}.cls-4{stroke-width:2.25px;}.cls-5{stroke-width:4px;}.cls-6{fill:#050606;}</style></defs><g id="Layer_5" data-name="Layer 5"><path class="cls-1" d="M1517.73,392.65h0a102.1,102.1,0,0,0-102.1,102.1V770.37A40.62,40.62,0,0,1,1375,811H455.16a48.49,48.49,0,0,0-48.48,48.48v126a11.85,11.85,0,0,0,3.46,8.37l15.34,15.34a11.81,11.81,0,0,1,3.47,8.37v137.16a11.81,11.81,0,0,1-3.47,8.37l-15.34,15.34a11.85,11.85,0,0,0-3.46,8.37v112.67a48.49,48.49,0,0,0,48.48,48.49H1571.34a48.51,48.51,0,0,0,48.49-48.5V494.75A102.1,102.1,0,0,0,1517.73,392.65Zm-110.61,815V954a33.14,33.14,0,0,1,66.27,0v253.65a33.14,33.14,0,0,1-66.27,0Z"></path><path class="cls-2" d="M1516,439.16c-30.23.91-53.92,26.54-53.92,56.79V770.37A87.11,87.11,0,0,1,1375,857.48H732.31A27.51,27.51,0,0,0,704.8,885v388.93a27.51,27.51,0,0,0,27.51,27.51h828.38a12.7,12.7,0,0,0,12.65-12.65v-794A55.69,55.69,0,0,0,1516,439.16Zm-108.9,768.47V954a33.14,33.14,0,0,1,66.27,0v253.65a33.14,33.14,0,0,1-66.27,0Z"></path><rect class="cls-3" x="787.14" y="943.38" width="429.45" height="224.42"></rect><path class="cls-1" d="M1478.6,915.35A54.23,54.23,0,0,0,1386,953.69v254.23a54.23,54.23,0,1,0,108.45,0V953.69A54,54,0,0,0,1478.6,915.35Zm-5.21,292.28a33.14,33.14,0,0,1-66.27,0V954a33.14,33.14,0,0,1,66.27,0Z"></path></g><g id="Layer_2" data-name="Layer 2"><path class="cls-4" d="M1573.34,494.75v794a12.68,12.68,0,0,1-12.65,12.65H732.31a27.51,27.51,0,0,1-27.51-27.51V885a27.51,27.51,0,0,1,27.51-27.51H1375a87.11,87.11,0,0,0,87.11-87.11V496c0-30.25,23.69-55.88,53.92-56.79A55.69,55.69,0,0,1,1573.34,494.75Z"></path><path class="cls-5" d="M410.14,1178.39,425.49,1163a11.78,11.78,0,0,0,3.46-8.35V1017.5a11.8,11.8,0,0,0-3.46-8.35l-15.35-15.36a11.77,11.77,0,0,1-3.46-8.35v-126A48.47,48.47,0,0,1,455.16,811H1375a40.63,40.63,0,0,0,40.63-40.63V494.75a102.1,102.1,0,0,1,102.1-102.1h0a102.1,102.1,0,0,1,102.1,102.1v804.66a48.51,48.51,0,0,1-48.49,48.5H455.16a48.48,48.48,0,0,1-48.48-48.49V1186.74A11.78,11.78,0,0,1,410.14,1178.39Z"></path><rect class="cls-4" x="1407.12" y="920.85" width="66.26" height="319.9" rx="33.13"></rect><rect class="cls-4" x="1386.03" y="899.46" width="108.46" height="362.69" rx="54.23"></rect><path class="cls-6" d="M639.76,1070.55a2.91,2.91,0,0,1-2.91-2.91v-30.53a5.42,5.42,0,0,0-1.6-3.86l-32.44-32.44a11.86,11.86,0,0,1-3.5-8.44V901a12.52,12.52,0,0,0-12.51-12.51H483.92a12.7,12.7,0,0,0-12.68,12.69v76.78a24.13,24.13,0,0,0,7.11,17.18l14.33,14.33a24.13,24.13,0,0,0,17.18,7.11h50.75a11.86,11.86,0,0,1,8.44,3.5l24.26,24.26a12.47,12.47,0,0,1,3.68,8.88v14.46a2.91,2.91,0,1,1-5.81,0v-14.46a6.72,6.72,0,0,0-2-4.77l-24.26-24.26a6.09,6.09,0,0,0-4.33-1.8H509.86a29.91,29.91,0,0,1-21.29-8.81l-14.33-14.33a29.87,29.87,0,0,1-8.81-21.29V901.14a18.51,18.51,0,0,1,18.49-18.5H586.8A18.34,18.34,0,0,1,605.12,901v91.41a6.09,6.09,0,0,0,1.8,4.33l32.44,32.44a11.19,11.19,0,0,1,3.3,8v30.53A2.9,2.9,0,0,1,639.76,1070.55Z"></path><path class="cls-6" d="M586.8,1289.46H483.92a18.51,18.51,0,0,1-18.49-18.5v-76.78a29.87,29.87,0,0,1,8.81-21.29l14.33-14.34a29.91,29.91,0,0,1,21.29-8.81h50.75a6.09,6.09,0,0,0,4.33-1.8l24.26-24.25a6.74,6.74,0,0,0,2-4.78v-14.46a2.91,2.91,0,0,1,5.81,0v14.46a12.51,12.51,0,0,1-3.68,8.89l-24.26,24.25a11.86,11.86,0,0,1-8.44,3.5H509.86a24.17,24.17,0,0,0-17.18,7.11L478.35,1177a24.09,24.09,0,0,0-7.11,17.18V1271a12.71,12.71,0,0,0,12.68,12.69H586.8a12.53,12.53,0,0,0,12.51-12.52v-91.4a11.83,11.83,0,0,1,3.5-8.44l32.44-32.44a5.46,5.46,0,0,0,1.6-3.87v-30.53a2.91,2.91,0,0,1,5.81,0V1135a11.19,11.19,0,0,1-3.3,8l-32.44,32.45a6.06,6.06,0,0,0-1.8,4.33v91.4A18.35,18.35,0,0,1,586.8,1289.46Z"></path><rect class="cls-4" x="787.14" y="943.38" width="429.45" height="224.42"></rect></g></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 3.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 32 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="528.89 806.04 942.22 446.84"><defs><style>.cls-1{fill:#e8eae8;}.cls-2{fill:#dbdddb;}.cls-3{fill:#c6842a;}.cls-4,.cls-5,.cls-7,.cls-9{fill:none;stroke-miterlimit:10;}.cls-4,.cls-5{stroke:#050606;}.cls-4,.cls-9{stroke-width:2.44px;}.cls-5,.cls-7{stroke-width:1.22px;}.cls-6{fill:#b7b7b7;}.cls-7,.cls-9{stroke:#b7b7b7;}.cls-8{fill:#cbcccb;}.cls-10{fill:#434543;}</style></defs><g id="Layer_4" data-name="Layer 4"><path class="cls-1" d="M1469.9,826.68v390.94a19.43,19.43,0,0,1-19.43,19.43H549.53a19.43,19.43,0,0,1-19.43-19.43V826.68a19.42,19.42,0,0,1,19.43-19.42h900.94A19.42,19.42,0,0,1,1469.9,826.68Z"></path><path class="cls-2" d="M574.23,807.26v429.79h-24.7a19.43,19.43,0,0,1-19.43-19.43V826.68a19.42,19.42,0,0,1,19.43-19.42Z"></path><path class="cls-2" d="M1469.9,826.68v390.94a19.43,19.43,0,0,1-19.43,19.43h-37.56V807.26h37.56A19.42,19.42,0,0,1,1469.9,826.68Z"></path><path class="cls-3" d="M574.23,1129.8h-7.47a4.55,4.55,0,0,1-4.55-4.54V919.05a4.55,4.55,0,0,1,4.55-4.55h7.47"></path><rect class="cls-4" x="530.11" y="807.26" width="939.78" height="429.79" rx="19.42"></rect><line class="cls-5" x1="574.23" y1="807.26" x2="574.23" y2="1237.05"></line><path class="cls-5" d="M574.23,1129.8h-7.47a4.55,4.55,0,0,1-4.55-4.54V919.05a4.55,4.55,0,0,1,4.55-4.55h7.47"></path><rect class="cls-6" x="599.01" y="970.1" width="11.52" height="104.11"></rect><rect class="cls-5" x="599.01" y="970.1" width="11.52" height="104.11"></rect><path class="cls-2" d="M610.53,816.78V935.32l38.37,11.55a7.85,7.85,0,0,1,5.6,7.53V1107a7.87,7.87,0,0,1-7.87,7.87h-36.1v110.58H1406V816.78Zm775.41,384.75H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66h754.51Z"></path><path class="cls-1" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><path class="cls-7" d="M610.53,816.78V935.32l38.37,11.55a7.85,7.85,0,0,1,5.6,7.53V1107a7.87,7.87,0,0,1-7.87,7.87h-36.1v110.58H1406V816.78Zm775.41,384.75H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66h754.51Z"></path><path class="cls-7" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><path class="cls-7" d="M1385.94,840.45v361.08H631.43a3.66,3.66,0,0,1-3.66-3.66V1138a3.65,3.65,0,0,1,3.66-3.65h28.3a14.7,14.7,0,0,0,14.71-14.71V931a14.7,14.7,0,0,0-14.71-14.71h-28.3a3.65,3.65,0,0,1-3.66-3.66V844.11a3.66,3.66,0,0,1,3.66-3.66Z"></path><line class="cls-7" x1="666.4" y1="1132.79" x2="666.4" y2="1201.53"></line><line class="cls-7" x1="663.66" y1="916.86" x2="663.66" y2="840.45"></line><circle class="cls-8" cx="644.99" cy="878.66" r="10.7"></circle><circle class="cls-8" cx="644.99" cy="1171.55" r="10.7"></circle><circle class="cls-9" cx="644.99" cy="878.66" r="10.7"></circle><circle class="cls-9" cx="644.99" cy="1171.55" r="10.7"></circle><path class="cls-10" d="M1225,1237.05l2.23,11.19a4.25,4.25,0,0,0,4.17,3.42H1249a4.26,4.26,0,0,0,4.18-3.42l2.22-11.19"></path><path class="cls-10" d="M1306.87,1237.05l2.22,11.19a4.26,4.26,0,0,0,4.18,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.22-11.19"></path><path class="cls-10" d="M1388.77,1237.05l2.23,11.19a4.24,4.24,0,0,0,4.17,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.23-11.19"></path><path class="cls-4" d="M1225,1237.05l2.23,11.19a4.25,4.25,0,0,0,4.17,3.42H1249a4.26,4.26,0,0,0,4.18-3.42l2.22-11.19"></path><path class="cls-4" d="M1306.87,1237.05l2.22,11.19a4.26,4.26,0,0,0,4.18,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.22-11.19"></path><path class="cls-4" d="M1388.77,1237.05l2.23,11.19a4.24,4.24,0,0,0,4.17,3.42h17.62a4.25,4.25,0,0,0,4.17-3.42l2.23-11.19"></path><line class="cls-4" x1="1412.9" y1="807.26" x2="1412.9" y2="1237.05"></line></g></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 4.1 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.1 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="479.57 786.58 1040.84 433.17"><defs><style>.cls-1{fill:#cccccb;}.cls-2{fill:#2b2b2b;}.cls-3,.cls-6,.cls-7,.cls-8{fill:none;stroke-miterlimit:10;}.cls-3,.cls-6,.cls-7{stroke:#050606;}.cls-3,.cls-8{stroke-width:1.65px;}.cls-4{fill:#40403f;}.cls-5{fill:#ddd;}.cls-6{stroke-width:1.62px;}.cls-7{stroke-width:1.64px;}.cls-8{stroke:#fff;}.cls-9{fill:#353535;}.cls-10{fill:#c08c2d;}</style></defs><g id="Layer_4" data-name="Layer 4"><path class="cls-1" d="M595,923.44H519.6A10.46,10.46,0,0,1,509.14,913V802.7a15.28,15.28,0,0,1,15.28-15.28h979.89a15.29,15.29,0,0,1,15.29,15.29v400.93a15.3,15.3,0,0,1-15.29,15.29H524.42a15.28,15.28,0,0,1-15.28-15.28V1102.1a10.46,10.46,0,0,1,10.46-10.46H595"></path><rect class="cls-2" x="611.37" y="796.48" width="819.83" height="411.47"></rect><line class="cls-3" x1="1441.99" y1="787.41" x2="1441.99" y2="1218.92"></line><path class="cls-4" d="M620.91,851.7v302.78a1.87,1.87,0,0,1-1.87,1.87h-13.8a8.7,8.7,0,0,1-.89,0,10.23,10.23,0,0,1-9.35-10.2v-286a10.24,10.24,0,0,1,9.35-10.2,8.7,8.7,0,0,1,.89,0H619A1.87,1.87,0,0,1,620.91,851.7Z"></path><rect class="cls-5" x="480.4" y="942.42" width="114.6" height="127.58"></rect><rect class="cls-3" x="480.4" y="942.42" width="114.6" height="127.58"></rect><path class="cls-6" d="M595,923.44H519.6A10.46,10.46,0,0,1,509.14,913V802.7a15.28,15.28,0,0,1,15.28-15.28h979.89a15.29,15.29,0,0,1,15.29,15.29v400.93a15.3,15.3,0,0,1-15.29,15.29H524.42a15.28,15.28,0,0,1-15.28-15.28V1102.1a10.46,10.46,0,0,1,10.46-10.46H595"></path><path class="cls-2" d="M584.65,970.14H595a0,0,0,0,1,0,0v24.44a0,0,0,0,1,0,0H584.65a3,3,0,0,1-3-3V973.11A3,3,0,0,1,584.65,970.14Z"></path><rect class="cls-2" x="560.58" y="976.5" width="9.04" height="16.58" rx="2.72"></rect><path class="cls-2" d="M584.65,1026.63H595a0,0,0,0,1,0,0v24.44a0,0,0,0,1,0,0H584.65a3,3,0,0,1-3-3v-18.49A3,3,0,0,1,584.65,1026.63Z"></path><rect class="cls-2" x="560.58" y="1028.91" width="9.04" height="16.58" rx="2.72"></rect><path class="cls-3" d="M584.65,970.14H595a0,0,0,0,1,0,0v24.44a0,0,0,0,1,0,0H584.65a3,3,0,0,1-3-3V973.11A3,3,0,0,1,584.65,970.14Z"></path><rect class="cls-3" x="560.58" y="976.5" width="9.04" height="16.58" rx="2.72"></rect><path class="cls-3" d="M584.65,1026.63H595a0,0,0,0,1,0,0v24.44a0,0,0,0,1,0,0H584.65a3,3,0,0,1-3-3v-18.49A3,3,0,0,1,584.65,1026.63Z"></path><rect class="cls-3" x="560.58" y="1028.91" width="9.04" height="16.58" rx="2.72"></rect><polyline class="cls-7" points="611.37 1156.35 611.37 1207.95 1431.2 1207.95 1431.2 796.48 611.37 796.48 611.37 849.83"></polyline><line class="cls-3" x1="611.37" y1="1207.95" x2="611.37" y2="1218.93"></line><line class="cls-3" x1="611.37" y1="796.48" x2="611.37" y2="787.42"></line><rect class="cls-8" x="560.58" y="1107.17" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="528.51" y="1107.17" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="560.58" y="1166.28" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="528.51" y="1166.28" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="560.58" y="804.46" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="528.51" y="804.46" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="560.58" y="863.57" width="18.37" height="41.67" rx="4.91"></rect><rect class="cls-8" x="528.51" y="863.57" width="18.37" height="41.67" rx="4.91"></rect><circle class="cls-8" cx="1476.63" cy="831.74" r="27.15"></circle><circle class="cls-8" cx="1476.63" cy="1173.49" r="27.15"></circle><rect class="cls-9" x="676.15" y="804.6" width="742.79" height="396.03"></rect><path class="cls-10" d="M604.35,849.87v306.44a10.23,10.23,0,0,1-9.35-10.2v-286A10.24,10.24,0,0,1,604.35,849.87Z"></path><path class="cls-3" d="M605.24,849.83H619a1.87,1.87,0,0,1,1.87,1.87v302.78a1.87,1.87,0,0,1-1.87,1.87h-13.8A10.24,10.24,0,0,1,595,1146.11v-286A10.24,10.24,0,0,1,605.24,849.83Z"></path><rect class="cls-6" x="676.15" y="804.6" width="742.79" height="396.03"></rect></g></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 3.9 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 9.9 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 9.9 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 83 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 83 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 43 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 8.3 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 102 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 71 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 5.3 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 176 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 164 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 11 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 128 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 9.0 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 76 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 8.7 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 28 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 36 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 31 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 23 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 8.0 KiB |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="733.42 451.82 573.87 931.48"><defs><style>.cls-1{fill:#8e8d8e;}.cls-2{fill:#383839;}.cls-3{fill:#cccccb;}.cls-4{fill:#222226;}.cls-5,.cls-6{fill:none;stroke:#050606;stroke-miterlimit:10;}.cls-5{stroke-width:1.87px;}.cls-6{stroke-width:3.77px;}.cls-7{fill:#4c4c4d;}</style></defs><g id="Layer_4" data-name="Layer 4"><path class="cls-1" d="M1277.27,847.59h4.35a8.09,8.09,0,0,1,8.09,8.08v138a8.09,8.09,0,0,1-8.09,8.09h-4.35"></path><path class="cls-1" d="M1277.27,732.73h18a10.14,10.14,0,0,1,10.14,10.14v43A10.14,10.14,0,0,1,1295.26,796h-18a0,0,0,0,1,0,0V732.73A0,0,0,0,1,1277.27,732.73Z"></path><path class="cls-2" d="M1256.49,1200.6h0a14.19,14.19,0,0,1-2.83,12.5c-8.13,9.86-19.94,18.58-46,30.75-19.15,9-28.65,16-38.35,29.6a93.15,93.15,0,0,0-8.7,14.61c-6.95,15.17-11.77,44.44-11.77,65.66v3.61a24.09,24.09,0,0,1-24.1,24.09H887.83a24.09,24.09,0,0,1-24.1-24.09v-3.61c0-21.22-4.82-50.49-11.77-65.66a93.15,93.15,0,0,0-8.7-14.61c-9.7-13.63-19.2-20.65-38.35-29.6-26.06-12.17-37.87-20.89-46-30.75a14.22,14.22,0,0,1-2.82-12.5h0"></path><path class="cls-2" d="M756.09,634.53h0a14.19,14.19,0,0,1,2.83-12.5c8.12-9.86,19.93-18.58,46-30.75,19.15-8.95,28.65-16,38.35-29.6a93.15,93.15,0,0,0,8.7-14.61c6.95-15.17,11.77-44.44,11.77-65.66V477.8a24.09,24.09,0,0,1,24.1-24.09h236.92a24.09,24.09,0,0,1,24.1,24.09v3.61c0,21.22,4.82,50.49,11.77,65.66a93.15,93.15,0,0,0,8.7,14.61c9.7,13.63,19.2,20.65,38.35,29.6,26,12.17,37.86,20.89,46,30.75a14.19,14.19,0,0,1,2.83,12.5h0"></path><rect class="cls-3" x="735.31" y="598.25" width="541.96" height="638.99" rx="96.44"></rect><path class="cls-2" d="M1247.38,694.68v446.11a66.63,66.63,0,0,1-66.54,66.56H831.75a66.62,66.62,0,0,1-66.56-66.56V694.68a66.63,66.63,0,0,1,66.56-66.55h349.09A66.64,66.64,0,0,1,1247.38,694.68Z"></path><rect class="cls-4" x="817.71" y="721.76" width="379.03" height="388.6"></rect><path class="cls-5" d="M1247.38,694.68v446.11a66.63,66.63,0,0,1-66.54,66.56H831.75a66.62,66.62,0,0,1-66.56-66.56V694.68a66.63,66.63,0,0,1,66.56-66.55h349.09A66.64,66.64,0,0,1,1247.38,694.68Z"></path><rect class="cls-6" x="735.31" y="598.25" width="541.96" height="638.99" rx="96.44"></rect><path class="cls-6" d="M1256.49,1200.6h0a14.19,14.19,0,0,1-2.83,12.5c-8.13,9.86-19.94,18.58-46,30.75-19.15,9-28.65,16-38.35,29.6a93.15,93.15,0,0,0-8.7,14.61c-6.95,15.17-11.77,44.44-11.77,65.66v3.61a24.09,24.09,0,0,1-24.1,24.09H887.83a24.09,24.09,0,0,1-24.1-24.09v-3.61c0-21.22-4.82-50.49-11.77-65.66a93.15,93.15,0,0,0-8.7-14.61c-9.7-13.63-19.2-20.65-38.35-29.6-26.06-12.17-37.87-20.89-46-30.75a14.22,14.22,0,0,1-2.82-12.5h0"></path><path class="cls-6" d="M756.09,634.53h0a14.19,14.19,0,0,1,2.83-12.5c8.12-9.86,19.93-18.58,46-30.75,19.15-8.95,28.65-16,38.35-29.6a93.15,93.15,0,0,0,8.7-14.61c6.95-15.17,11.77-44.44,11.77-65.66V477.8a24.09,24.09,0,0,1,24.1-24.09h236.92a24.09,24.09,0,0,1,24.1,24.09v3.61c0,21.22,4.82,50.49,11.77,65.66a93.15,93.15,0,0,0,8.7,14.61c9.7,13.63,19.2,20.65,38.35,29.6,26,12.17,37.86,20.89,46,30.75a14.19,14.19,0,0,1,2.83,12.5h0"></path><rect class="cls-5" x="817.71" y="721.76" width="379.03" height="388.6"></rect><path class="cls-6" d="M1277.27,847.59h4.35a8.09,8.09,0,0,1,8.09,8.08v138a8.09,8.09,0,0,1-8.09,8.09h-4.35"></path><path class="cls-6" d="M1277.27,732.73h18a10.14,10.14,0,0,1,10.14,10.14v43A10.14,10.14,0,0,1,1295.26,796h-18a0,0,0,0,1,0,0V732.73A0,0,0,0,1,1277.27,732.73Z"></path><circle class="cls-7" cx="1083.08" cy="1177.35" r="16.6"></circle><rect class="cls-2" x="1280.24" y="739.77" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="750.91" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="762.06" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="773.2" width="16.77" height="4.59" rx="2.29"></rect><rect class="cls-2" x="1280.24" y="784.34" width="16.77" height="4.59" rx="2.29"></rect></g></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 3.8 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 70 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 112 KiB |
|
@ -1,109 +0,0 @@
|
|||
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1" id="svg105" sodipodi:docname="thinknode_m1.svg" inkscape:version="1.4 (e7c3feb1, 2024-10-09)" viewBox="397.31 77.24 361 863.17">
|
||||
<sodipodi:namedview id="namedview105" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="4.066786" inkscape:cx="564.94244" inkscape:cy="741.49463" inkscape:window-width="1472" inkscape:window-height="890" inkscape:window-x="0" inkscape:window-y="38" inkscape:window-maximized="1" inkscape:current-layer="Layer_3"/>
|
||||
<defs id="defs1">
|
||||
<style id="style1">.cls-1{fill:#353535;}.cls-2{fill:#262626;}.cls-3{fill:#cccccb;}.cls-4{fill:#2b2b2b;}.cls-5{fill:#f05043;}.cls-6{fill:#3d3d3d;}.cls-7{fill:#231f20;}.cls-8{fill:none;stroke:#000;stroke-miterlimit:10;}</style>
|
||||
</defs>
|
||||
<g id="Layer_3" data-name="Layer 3">
|
||||
<path class="cls-1" d="M720.82,449.91h11.45a19.68,19.68,0,0,1,19.67,19.68V905.12a28.48,28.48,0,0,1-28.47,28.48H425.72A27.77,27.77,0,0,1,397.81,906V470.82a21,21,0,0,1,21.13-20.91h23.74" id="path1"/>
|
||||
<rect class="cls-2" x="447.12" y="523.83" width="266.09" height="266.09" rx="22.7" id="rect1"/>
|
||||
<rect class="cls-1" x="465.51" y="542.22" width="229.3" height="229.3" rx="12.91" id="rect2"/>
|
||||
<rect class="cls-3" x="476.07" y="552.78" width="208.17" height="208.17" rx="7.83" id="rect3"/>
|
||||
<path class="cls-1" d="M507.38,77.74H472.16a7,7,0,0,0-7,7V359.93L452.2,396.26v39.91H561V396.26l-13.3-36V84.15a6.41,6.41,0,0,0-6.41-6.41Z" id="path3"/>
|
||||
<rect class="cls-2" x="454.25" y="436.17" width="104.38" height="3.65" id="rect4"/>
|
||||
<polygon class="cls-1" points="442.68 449.91 448.16 440.69 562.98 440.69 570.51 449.91 442.68 449.91" id="polygon4"/>
|
||||
<rect class="cls-1" x="604.37" y="355.96" width="105.26" height="60.65" rx="4.8" id="rect5"/>
|
||||
<path class="cls-2" d="M611.2,356v-5.48a3.13,3.13,0,0,1,3.13-3.13h86.35a3.13,3.13,0,0,1,3.13,3.13V356Z" id="path5"/>
|
||||
<rect class="cls-2" x="611.07" y="416.61" width="92.74" height="23.22" id="rect6"/>
|
||||
<polygon class="cls-1" points="592.99 449.91 598.47 440.69 713.42 440.69 720.82 449.91 592.99 449.91" id="polygon6"/>
|
||||
<rect class="cls-2" x="751.94" y="555.13" width="5.87" height="47.48" id="rect7"/>
|
||||
<path class="cls-2" d="M751.94,683.87h2.72a3.15,3.15,0,0,1,3.15,3.15v49.17a3.15,3.15,0,0,1-3.15,3.15h-2.72a0,0,0,0,1,0,0V683.87A0,0,0,0,1,751.94,683.87Z" id="path7"/>
|
||||
<path class="cls-2" d="M751.94,781.43h2.72a3.15,3.15,0,0,1,3.15,3.15v49.17a3.15,3.15,0,0,1-3.15,3.15h-2.72a0,0,0,0,1,0,0V781.43A0,0,0,0,1,751.94,781.43Z" id="path8"/>
|
||||
<path class="cls-4" d="M425.72,933.6l17.46-41.05a15.2,15.2,0,0,1,14-9.25H702.88A15.19,15.19,0,0,1,717,892.9l15.52,39.22" id="path9"/>
|
||||
<rect class="cls-2" x="505.03" y="841.57" width="147.52" height="24.65" rx="12.33" id="rect9"/>
|
||||
<circle class="cls-5" cx="518.72" cy="853.89" r="5.48" id="circle9"/>
|
||||
<circle class="cls-1" cx="640.14" cy="853.89" r="5.48" id="circle10"/>
|
||||
<circle class="cls-1" cx="541.83" cy="853.89" r="5.48" id="circle11"/>
|
||||
<circle class="cls-1" cx="567.67" cy="853.89" r="5.48" id="circle12"/>
|
||||
<circle class="cls-1" cx="593.51" cy="853.89" r="5.48" id="circle13"/>
|
||||
<circle class="cls-1" cx="616.82" cy="853.89" r="5.48" id="circle14"/>
|
||||
<path class="cls-4" d="M428.2,933.6v4.1a2.21,2.21,0,0,0,2.22,2.21h11.22a2.21,2.21,0,0,0,2.21-2.21v-4.1" id="path14"/>
|
||||
<path class="cls-4" d="M713.2,933.6v4.1a2.21,2.21,0,0,0,2.22,2.21h11.22a2.21,2.21,0,0,0,2.21-2.21v-4.1" id="path15"/>
|
||||
<path class="cls-6" d="M494.46,449.91v5.59a12.22,12.22,0,0,0,1.05,4.95l8.6,19.42a9.43,9.43,0,0,0,8.62,5.61h3.61a9.43,9.43,0,0,0,9.43-9.43V449.91" id="path16"/>
|
||||
<path class="cls-6" d="M672.56,449.91v5.59a12.22,12.22,0,0,1-1,4.95l-8.6,19.42a9.43,9.43,0,0,1-8.62,5.61h-3.61a9.43,9.43,0,0,1-9.43-9.43V449.91" id="path17"/>
|
||||
<path class="cls-6" d="M532.42,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,532.42,449.91Z" id="path18"/>
|
||||
<path class="cls-6" d="M559.81,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,559.81,449.91Z" id="path19"/>
|
||||
<path class="cls-6" d="M587.2,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,587.2,449.91Z" id="path20"/>
|
||||
<path class="cls-6" d="M613.81,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,613.81,449.91Z" id="path21"/>
|
||||
<path class="cls-1" d="M477,924.32h-3V903.09h-7.46v-2.65h17.9v2.65H477Z" id="path51"/>
|
||||
<path class="cls-1" d="M490.59,906.36c0,.43,0,.86,0,1.31s-.07.85-.12,1.2h.2a5.17,5.17,0,0,1,1.44-1.54,7.08,7.08,0,0,1,1.94-.92,7.81,7.81,0,0,1,2.21-.31,8.61,8.61,0,0,1,3.63.68,4.62,4.62,0,0,1,2.19,2.13,8.22,8.22,0,0,1,.73,3.74v11.67h-2.9V912.85a4.72,4.72,0,0,0-1-3.24,3.92,3.92,0,0,0-3.05-1.07,5.65,5.65,0,0,0-3.14.75,4.07,4.07,0,0,0-1.62,2.21,11.17,11.17,0,0,0-.49,3.56v9.26h-2.94V898.91h2.94Z" id="path52"/>
|
||||
<path class="cls-1" d="M509.82,899.67a1.73,1.73,0,0,1,1.19.46,2.17,2.17,0,0,1,0,2.82,1.74,1.74,0,0,1-1.19.47,1.77,1.77,0,0,1-1.24-.47,2.24,2.24,0,0,1,0-2.82A1.76,1.76,0,0,1,509.82,899.67Zm1.44,6.73v17.92h-2.94V906.4Z" id="path53"/>
|
||||
<path class="cls-1" d="M525.58,906.06a6.8,6.8,0,0,1,4.85,1.56c1.09,1,1.63,2.71,1.63,5v11.67h-2.91V912.85a4.67,4.67,0,0,0-1-3.24,3.88,3.88,0,0,0-3-1.07c-2,0-3.36.56-4.11,1.67a8.54,8.54,0,0,0-1.14,4.82v9.29H517V906.4h2.37l.44,2.44h.16a5.68,5.68,0,0,1,1.49-1.56,6.41,6.41,0,0,1,2-.92A8.13,8.13,0,0,1,525.58,906.06Z" id="path54"/>
|
||||
<path class="cls-1" d="M540.53,912.18c0,.36,0,.83,0,1.41s-.07,1.08-.09,1.5h.14l.6-.77.82-1c.28-.34.52-.63.72-.85l5.72-6.05h3.44l-7.26,7.66,7.76,10.26h-3.54L542.57,916l-2,1.78v6.58h-2.91V898.91h2.91Z" id="path55"/>
|
||||
<path class="cls-1" d="M574.81,924.32H571.3l-12.78-19.83h-.13c0,.51.08,1.12.11,1.82s.07,1.45.1,2.24,0,1.61,0,2.43v13.34h-2.77V900.44h3.48l12.74,19.77h.13c0-.36-.05-.89-.08-1.6s-.07-1.5-.1-2.35,0-1.62,0-2.34V900.44h2.81Z" id="path56"/>
|
||||
<path class="cls-1" d="M596.48,915.33a12.32,12.32,0,0,1-.58,4,8.32,8.32,0,0,1-1.67,2.93,7,7,0,0,1-2.65,1.82,9.31,9.31,0,0,1-3.46.62,8.63,8.63,0,0,1-3.28-.62,7.29,7.29,0,0,1-2.61-1.82,8.57,8.57,0,0,1-1.72-2.93,11.76,11.76,0,0,1-.62-4,11.43,11.43,0,0,1,1-5,7.12,7.12,0,0,1,2.87-3.14,8.76,8.76,0,0,1,4.45-1.09,8.4,8.4,0,0,1,4.3,1.09,7.45,7.45,0,0,1,2.91,3.14A11,11,0,0,1,596.48,915.33Zm-13.54,0a10.93,10.93,0,0,0,.55,3.66,4.82,4.82,0,0,0,1.72,2.39,5.69,5.69,0,0,0,5.95,0,4.78,4.78,0,0,0,1.73-2.39,10.93,10.93,0,0,0,.55-3.66,10.36,10.36,0,0,0-.57-3.65,4.84,4.84,0,0,0-1.72-2.32,5,5,0,0,0-3-.82,4.5,4.5,0,0,0-4,1.8A8.79,8.79,0,0,0,582.94,915.33Z" id="path57"/>
|
||||
<path class="cls-1" d="M607.49,924.66a6.67,6.67,0,0,1-5.35-2.33c-1.34-1.54-2-3.86-2-6.94s.67-5.4,2-7a6.74,6.74,0,0,1,5.37-2.36,7.71,7.71,0,0,1,2.44.35,6.37,6.37,0,0,1,1.81,1,6.58,6.58,0,0,1,1.3,1.34h.2c0-.29-.06-.72-.11-1.29s-.09-1-.09-1.36v-7.15H616v25.41h-2.38l-.43-2.4h-.14a6.51,6.51,0,0,1-1.3,1.38,5.9,5.9,0,0,1-1.82,1A7.4,7.4,0,0,1,607.49,924.66Zm.46-2.44c1.9,0,3.23-.52,4-1.56a7.84,7.84,0,0,0,1.16-4.7v-.53a9.84,9.84,0,0,0-1.11-5.14c-.73-1.19-2.09-1.79-4.08-1.79a4,4,0,0,0-3.56,1.89,9.46,9.46,0,0,0-1.19,5.07,9,9,0,0,0,1.19,5A4,4,0,0,0,608,922.22Z" id="path58"/>
|
||||
<path class="cls-1" d="M628.62,906.06a7.53,7.53,0,0,1,4,1,6.62,6.62,0,0,1,2.54,2.82,9.69,9.69,0,0,1,.89,4.27v1.77H623.74a6.75,6.75,0,0,0,1.56,4.63,5.42,5.42,0,0,0,4.16,1.59,12.58,12.58,0,0,0,3-.32,16.78,16.78,0,0,0,2.72-.92v2.58a13.84,13.84,0,0,1-2.71.89,16.15,16.15,0,0,1-3.17.28,9.46,9.46,0,0,1-4.5-1,7.15,7.15,0,0,1-3-3.09,10.61,10.61,0,0,1-1.09-5,12,12,0,0,1,1-5,7.33,7.33,0,0,1,6.94-4.38Zm0,2.41a4.26,4.26,0,0,0-3.33,1.36,6.34,6.34,0,0,0-1.45,3.76h9.13a7.05,7.05,0,0,0-.47-2.68,3.94,3.94,0,0,0-1.42-1.79A4.33,4.33,0,0,0,628.59,908.47Z" id="path59"/>
|
||||
<path class="cls-1" d="M639.36,913h8.1v2.74h-8.1Z" id="path60"/>
|
||||
<path class="cls-1" d="M662.87,924.32,655,903.39h-.13c0,.44.08,1,.12,1.7s.06,1.45.08,2.26,0,1.65,0,2.49v14.48h-2.77V900.44h4.45L664.15,920h.13l7.49-19.57h4.42v23.88h-3V909.64c0-.78,0-1.55,0-2.32s.06-1.5.1-2.18.08-1.25.1-1.72h-.13l-8,20.9Z" id="path61"/>
|
||||
<path class="cls-1" d="M688.16,924.32V909.41c0-.63,0-1.3,0-2s0-1.42.07-2.1,0-1.27,0-1.76c-.35.38-.66.69-.92.92s-.6.54-1,.92l-2.41,2-1.57-2,6.26-4.89H691v23.88Z" id="path62"/>
|
||||
<path class="cls-1" d="M502.55,894.19l-2.22-2.37a14.1,14.1,0,0,1,18.94-.33l-2.13,2.44a10.9,10.9,0,0,0-7.16-2.69A10.78,10.78,0,0,0,502.55,894.19Z" id="path63"/>
|
||||
<path class="cls-1" d="M506.38,897.85l-2.4-2.18a8.08,8.08,0,0,1,11.61-.39l-2.24,2.33a4.85,4.85,0,0,0-7,.24Z" id="path64"/>
|
||||
</g>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<path class="cls-8" d="M472.55,77.74h68.09a7.43,7.43,0,0,1,7.43,7.43V360.26a0,0,0,0,1,0,0h-83a0,0,0,0,1,0,0V85.17A7.43,7.43,0,0,1,472.55,77.74Z" id="path65"/>
|
||||
<line class="cls-8" x1="465.12" y1="123.91" x2="548.07" y2="123.91" id="line65"/>
|
||||
<line class="cls-8" x1="465.12" y1="149.74" x2="548.07" y2="149.74" id="line66"/>
|
||||
<polyline class="cls-8" points="465.12 360.26 452.2 396.26 452.2 436.17 560.99 436.17 560.99 396.26 548.07 360.26" id="polyline66"/>
|
||||
<line class="cls-8" x1="452.2" y1="396.26" x2="560.98" y2="396.26" id="line67"/>
|
||||
<path class="cls-8" d="M449.69,440.17H562a3.26,3.26,0,0,1,2.56,1.55l5.93,8.19H442.68l4-7.49A3.65,3.65,0,0,1,449.69,440.17Z" id="path67"/>
|
||||
<path class="cls-8" d="M600,440.17H712.33a3.24,3.24,0,0,1,2.56,1.55l5.93,8.19H593l4-7.49A3.65,3.65,0,0,1,600,440.17Z" id="path68"/>
|
||||
<line class="cls-8" x1="454.45" y1="436.17" x2="454.45" y2="439.83" id="line68"/>
|
||||
<line class="cls-8" x1="558.64" y1="436.17" x2="558.64" y2="439.83" id="line69"/>
|
||||
<rect class="cls-8" x="604.37" y="355.96" width="105.26" height="60.65" rx="4.87" id="rect69"/>
|
||||
<line class="cls-8" x1="611.07" y1="416.61" x2="611.07" y2="439.83" id="line70"/>
|
||||
<line class="cls-8" x1="703.81" y1="416.61" x2="703.81" y2="439.83" id="line71"/>
|
||||
<path class="cls-8" d="M614.2,347.35h86.48a3.13,3.13,0,0,1,3.13,3.13V356a0,0,0,0,1,0,0H611.07a0,0,0,0,1,0,0v-5.48A3.13,3.13,0,0,1,614.2,347.35Z" id="path71"/>
|
||||
<line class="cls-8" x1="570.51" y1="449.91" x2="592.99" y2="449.91" id="line72"/>
|
||||
<path class="cls-8" d="M720.82,449.91h11.45a19.68,19.68,0,0,1,19.67,19.68V905.12a28.48,28.48,0,0,1-28.47,28.48H425.72A27.77,27.77,0,0,1,397.81,906V470.82a21,21,0,0,1,21.13-20.91h23.74" id="path72"/>
|
||||
<rect class="cls-8" x="447.12" y="523.83" width="266.09" height="266.09" rx="22.7" id="rect72"/>
|
||||
<rect class="cls-8" x="465.51" y="542.22" width="229.3" height="229.3" rx="12.91" id="rect73"/>
|
||||
<rect class="cls-8" x="476.07" y="552.78" width="208.17" height="208.17" rx="7.83" id="rect74"/>
|
||||
<path class="cls-8" d="M494.46,449.91v5.59a12.22,12.22,0,0,0,1.05,4.95l8.6,19.42a9.43,9.43,0,0,0,8.62,5.61h3.61a9.43,9.43,0,0,0,9.43-9.43V449.91" id="path74"/>
|
||||
<path class="cls-8" d="M672.56,449.91v5.59a12.22,12.22,0,0,1-1,4.95l-8.6,19.42a9.43,9.43,0,0,1-8.62,5.61h-3.61a9.43,9.43,0,0,1-9.43-9.43V449.91" id="path75"/>
|
||||
<path class="cls-8" d="M532.42,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,532.42,449.91Z" id="path76"/>
|
||||
<path class="cls-8" d="M559.81,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,559.81,449.91Z" id="path77"/>
|
||||
<path class="cls-8" d="M587.2,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,587.2,449.91Z" id="path78"/>
|
||||
<path class="cls-8" d="M613.81,449.91h20.35a0,0,0,0,1,0,0v28.72a6.85,6.85,0,0,1-6.85,6.85h-6.65a6.85,6.85,0,0,1-6.85-6.85V449.91A0,0,0,0,1,613.81,449.91Z" id="path79"/>
|
||||
<rect class="cls-8" x="751.94" y="555.13" width="5.87" height="47.48" id="rect79"/>
|
||||
<path class="cls-8" d="M751.94,683.87h2.72a3.15,3.15,0,0,1,3.15,3.15v49.17a3.15,3.15,0,0,1-3.15,3.15h-2.72a0,0,0,0,1,0,0V683.87A0,0,0,0,1,751.94,683.87Z" id="path80"/>
|
||||
<path class="cls-8" d="M751.94,781.43h2.72a3.15,3.15,0,0,1,3.15,3.15v49.17a3.15,3.15,0,0,1-3.15,3.15h-2.72a0,0,0,0,1,0,0V781.43A0,0,0,0,1,751.94,781.43Z" id="path81"/>
|
||||
<path class="cls-8" d="M425.72,933.6l17.46-41.05a15.2,15.2,0,0,1,14-9.25H702.88A15.19,15.19,0,0,1,717,892.9l15.52,39.22" id="path82"/>
|
||||
<rect class="cls-8" x="505.03" y="841.57" width="147.52" height="24.65" rx="12.33" id="rect82"/>
|
||||
<circle class="cls-8" cx="518.72" cy="853.89" r="5.48" id="circle82"/>
|
||||
<circle class="cls-8" cx="640.14" cy="853.89" r="5.48" id="circle83"/>
|
||||
<circle class="cls-8" cx="541.83" cy="853.89" r="5.48" id="circle84"/>
|
||||
<circle class="cls-8" cx="567.67" cy="853.89" r="5.48" id="circle85"/>
|
||||
<circle class="cls-8" cx="593.51" cy="853.89" r="5.48" id="circle86"/>
|
||||
<circle class="cls-8" cx="616.82" cy="853.89" r="5.48" id="circle87"/>
|
||||
<line class="cls-8" x1="430.68" y1="572.74" x2="430.68" y2="602.61" id="line87"/>
|
||||
<line class="cls-8" x1="424.42" y1="595.43" x2="424.42" y2="578.11" id="line88"/>
|
||||
<line class="cls-8" x1="438.21" y1="595.43" x2="438.21" y2="578.11" id="line89"/>
|
||||
<line class="cls-8" x1="430.68" y1="644.74" x2="430.68" y2="674.61" id="line90"/>
|
||||
<line class="cls-8" x1="424.42" y1="667.43" x2="424.42" y2="650.11" id="line91"/>
|
||||
<line class="cls-8" x1="438.21" y1="667.43" x2="438.21" y2="650.11" id="line92"/>
|
||||
<line class="cls-8" x1="430.68" y1="716.74" x2="430.68" y2="746.61" id="line93"/>
|
||||
<line class="cls-8" x1="424.42" y1="739.43" x2="424.42" y2="722.11" id="line94"/>
|
||||
<line class="cls-8" x1="438.21" y1="739.43" x2="438.21" y2="722.11" id="line95"/>
|
||||
<line class="cls-8" x1="730.03" y1="572.74" x2="730.03" y2="602.61" id="line96"/>
|
||||
<line class="cls-8" x1="723.77" y1="595.43" x2="723.77" y2="578.11" id="line97"/>
|
||||
<line class="cls-8" x1="737.56" y1="595.43" x2="737.56" y2="578.11" id="line98"/>
|
||||
<line class="cls-8" x1="730.03" y1="644.74" x2="730.03" y2="674.61" id="line99"/>
|
||||
<line class="cls-8" x1="723.77" y1="667.43" x2="723.77" y2="650.11" id="line100"/>
|
||||
<line class="cls-8" x1="737.56" y1="667.43" x2="737.56" y2="650.11" id="line101"/>
|
||||
<line class="cls-8" x1="730.03" y1="716.74" x2="730.03" y2="746.61" id="line102"/>
|
||||
<line class="cls-8" x1="723.77" y1="739.43" x2="723.77" y2="722.11" id="line103"/>
|
||||
<line class="cls-8" x1="737.56" y1="739.43" x2="737.56" y2="722.11" id="line104"/>
|
||||
<path class="cls-8" d="M428.2,933.6v4.1a2.21,2.21,0,0,0,2.22,2.21h11.22a2.21,2.21,0,0,0,2.21-2.21v-4.1" id="path104"/>
|
||||
<path class="cls-8" d="M713.2,933.6v4.1a2.21,2.21,0,0,0,2.22,2.21h11.22a2.21,2.21,0,0,0,2.21-2.21v-4.1" id="path105"/>
|
||||
</g>
|
||||
</svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 15 KiB |
|
@ -1,391 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg75"
|
||||
sodipodi:docname="thinknode_m2.svg"
|
||||
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
|
||||
viewBox="388.5 121.73 413.05 787.86"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview75"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="3.7680002"
|
||||
inkscape:cx="265.65816"
|
||||
inkscape:cy="681.92672"
|
||||
inkscape:window-width="1472"
|
||||
inkscape:window-height="890"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="38"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_3" />
|
||||
<defs
|
||||
id="defs1">
|
||||
<style
|
||||
id="style1">.cls-1{fill:#262626;}.cls-2{fill:#353535;}.cls-3{fill:#303030;}.cls-4{fill:#f05043;}.cls-5,.cls-6,.cls-7,.cls-8{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-6{stroke-width:0.88px;}.cls-7{stroke-width:0.95px;}.cls-8{stroke-width:1px;}.cls-9{fill:#acdee5;}</style>
|
||||
</defs>
|
||||
<g
|
||||
id="Layer_3"
|
||||
data-name="Layer 3">
|
||||
<polygon
|
||||
class="cls-1"
|
||||
points="575.63 361.13 575.34 354.09 574.7 338.7 574.41 331.65 479.53 331.65 479.23 338.7 478.57 354.09 478.26 361.13 575.63 361.13"
|
||||
id="polygon1" />
|
||||
<polyline
|
||||
class="cls-2"
|
||||
points="458.33 403 473.46 384.87 579.68 384.87 595.03 403"
|
||||
id="polyline1" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M579.68,384.87l-.87-21.35a2.51,2.51,0,0,0-2.5-2.39H477.56a2.5,2.5,0,0,0-2.49,2.39l-.87,21.35"
|
||||
id="path1" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M578.32,351.57,577.88,341a2.41,2.41,0,0,0-2.41-2.32H478.41A2.42,2.42,0,0,0,476,341l-.43,10.55a2.42,2.42,0,0,0,2.42,2.52H575.9A2.43,2.43,0,0,0,578.32,351.57Z"
|
||||
id="path2" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M476.46,329.56a2,2,0,0,0,2,2.09h96.94a2,2,0,0,0,2-2.09l-7.89-193.08a14.91,14.91,0,0,0-14.9-14.31H499.26a14.91,14.91,0,0,0-14.9,14.31Z"
|
||||
id="path3" />
|
||||
<polyline
|
||||
class="cls-2"
|
||||
points="491.72 331.65 499.03 137.3 555.9 137.3 561.64 331.65"
|
||||
id="polyline3" />
|
||||
<rect
|
||||
class="cls-1"
|
||||
x="394.16"
|
||||
y="403"
|
||||
width="396"
|
||||
height="501.26"
|
||||
rx="48.72"
|
||||
id="rect3" />
|
||||
<rect
|
||||
class="cls-2"
|
||||
x="405.9"
|
||||
y="417.86"
|
||||
width="372.52"
|
||||
height="471.54"
|
||||
rx="38.16"
|
||||
id="rect4" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M763.35,521.78v329A23.38,23.38,0,0,1,740,874.13H441.22a23.38,23.38,0,0,1-23.38-23.38V456.51a23.38,23.38,0,0,1,23.38-23.38H675.28A18,18,0,0,1,688,438.41L757.66,508A19.43,19.43,0,0,1,763.35,521.78Z"
|
||||
id="path4" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M716.86,532.78H462.77a18,18,0,0,0-18,18V673.91a18,18,0,0,0,18,18H716.86a18,18,0,0,0,18-18V550.78A18,18,0,0,0,716.86,532.78Zm6.52,137.48a10.7,10.7,0,0,1-10.7,10.7H465.38a10.7,10.7,0,0,1-10.7-10.7V551.83a10.7,10.7,0,0,1,10.7-10.7h247.3a10.7,10.7,0,0,1,10.7,10.7Z"
|
||||
id="path5" />
|
||||
<rect
|
||||
x="454.68"
|
||||
y="541.13"
|
||||
width="268.7"
|
||||
height="139.83"
|
||||
rx="10.7"
|
||||
id="rect5" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M447,904.26v2.94a2,2,0,0,0,2,1.95h14.28a2,2,0,0,0,2-1.95v-2.94"
|
||||
id="path6" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M718.74,904.26v2.94a2,2,0,0,0,2,1.95H735a2,2,0,0,0,2-1.95v-2.94"
|
||||
id="path7" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M790.16,508.83h.39a10.56,10.56,0,0,1,10.56,10.56V656.57a10.56,10.56,0,0,1-10.56,10.56h-.39"
|
||||
id="path8" />
|
||||
<path
|
||||
class="cls-3"
|
||||
d="M394.16,518.17h-3.31a1.91,1.91,0,0,0-1.91,1.91V797a1.9,1.9,0,0,0,1.91,1.91h3.31"
|
||||
id="path9" />
|
||||
<rect
|
||||
class="cls-1"
|
||||
x="502.29"
|
||||
y="782"
|
||||
width="180.26"
|
||||
height="24.65"
|
||||
rx="12.33"
|
||||
id="rect9" />
|
||||
<circle
|
||||
class="cls-4"
|
||||
cx="515.99"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle9" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="637.4"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle10" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="660.08"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle11" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="539.09"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle12" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="564.93"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle13" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="590.77"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle14" />
|
||||
<circle
|
||||
class="cls-2"
|
||||
cx="614.09"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle15" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M475.77,856.71h-3.41V832.6h-8.47v-3H484.2v3h-8.43Z"
|
||||
id="path15" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M491.19,836.32c0,.48,0,1-.06,1.48s-.08,1-.13,1.37h.23a5.69,5.69,0,0,1,1.63-1.75,7.82,7.82,0,0,1,2.2-1,8.81,8.81,0,0,1,2.51-.36,9.64,9.64,0,0,1,4.12.78,5.2,5.2,0,0,1,2.49,2.41,9.43,9.43,0,0,1,.83,4.25v13.25h-3.3v-13a5.37,5.37,0,0,0-1.1-3.69,4.46,4.46,0,0,0-3.46-1.21,6.41,6.41,0,0,0-3.57.85,4.68,4.68,0,0,0-1.84,2.51,12.81,12.81,0,0,0-.55,4v10.52h-3.34V827.85h3.34Z"
|
||||
id="path16" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M513,828.73a2,2,0,0,1,1.35.51,2,2,0,0,1,.59,1.61,2.07,2.07,0,0,1-.59,1.6A2,2,0,0,1,513,833a2,2,0,0,1-1.4-.53,2.1,2.1,0,0,1-.57-1.6,2.06,2.06,0,0,1,.57-1.61A2,2,0,0,1,513,828.73Zm1.64,7.63v20.35h-3.35V836.36Z"
|
||||
id="path17" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M530.91,836a7.69,7.69,0,0,1,5.5,1.77c1.24,1.17,1.86,3.08,1.86,5.71v13.25H535v-13a5.37,5.37,0,0,0-1.1-3.69,4.46,4.46,0,0,0-3.46-1.21q-3.37,0-4.67,1.9a9.7,9.7,0,0,0-1.29,5.47v10.55h-3.34V836.36h2.7l.49,2.77h.19a6.17,6.17,0,0,1,1.69-1.76,7.31,7.31,0,0,1,2.22-1A9.16,9.16,0,0,1,530.91,836Z"
|
||||
id="path18" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M547.88,842.93q0,.6-.06,1.59t-.09,1.71h.15l.68-.87.93-1.16c.32-.39.59-.72.82-1l6.49-6.87h3.91l-8.24,8.69,8.81,11.66h-4l-7.06-9.49-2.32,2v7.48h-3.3V827.85h3.3Z"
|
||||
id="path19" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M586.8,856.71h-4l-14.5-22.52h-.15c.05.59.09,1.28.13,2.07s.07,1.65.11,2.55.06,1.81.06,2.75v15.15h-3.15V829.6h4L583.72,852h.16c0-.4-.06-1-.1-1.82s-.08-1.7-.11-2.66-.06-1.85-.06-2.66V829.6h3.19Z"
|
||||
id="path20" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M611.4,846.5a14.11,14.11,0,0,1-.66,4.5,9.41,9.41,0,0,1-1.9,3.32,7.92,7.92,0,0,1-3,2.07,10.53,10.53,0,0,1-3.93.7,9.66,9.66,0,0,1-3.72-.7,8.18,8.18,0,0,1-3-2.07,9.67,9.67,0,0,1-2-3.32,13.29,13.29,0,0,1-.7-4.5,13,13,0,0,1,1.14-5.72,8.25,8.25,0,0,1,3.26-3.57A10,10,0,0,1,602,836a9.47,9.47,0,0,1,4.87,1.23,8.61,8.61,0,0,1,3.31,3.57A12.41,12.41,0,0,1,611.4,846.5Zm-15.37,0a12.33,12.33,0,0,0,.62,4.15,5.45,5.45,0,0,0,2,2.72,6.49,6.49,0,0,0,6.76,0,5.5,5.5,0,0,0,2-2.72,12.32,12.32,0,0,0,.63-4.15,11.76,11.76,0,0,0-.65-4.14,5.53,5.53,0,0,0-1.95-2.64,5.76,5.76,0,0,0-3.4-.93,5.08,5.08,0,0,0-4.52,2.05A9.87,9.87,0,0,0,596,846.5Z"
|
||||
id="path21" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M623.9,857.09a7.62,7.62,0,0,1-6.08-2.64c-1.52-1.76-2.28-4.38-2.28-7.88s.77-6.13,2.3-7.91a7.61,7.61,0,0,1,6.09-2.68,8.58,8.58,0,0,1,2.78.4,6.79,6.79,0,0,1,2,1.08,7.87,7.87,0,0,1,1.48,1.52h.22c0-.33-.07-.82-.13-1.46s-.09-1.16-.09-1.54v-8.13h3.34v28.86h-2.7l-.49-2.73h-.15a7.83,7.83,0,0,1-1.48,1.57,6.86,6.86,0,0,1-2.07,1.12A8.44,8.44,0,0,1,623.9,857.09Zm.53-2.77q3.23,0,4.53-1.77a8.85,8.85,0,0,0,1.31-5.33v-.61a11.15,11.15,0,0,0-1.25-5.83c-.83-1.35-2.38-2-4.63-2a4.45,4.45,0,0,0-4,2.15,10.68,10.68,0,0,0-1.35,5.75,10.12,10.12,0,0,0,1.35,5.66A4.56,4.56,0,0,0,624.43,854.32Z"
|
||||
id="path22" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M647.89,836a8.5,8.5,0,0,1,4.5,1.14,7.45,7.45,0,0,1,2.89,3.21,11,11,0,0,1,1,4.84v2H642.35a7.71,7.71,0,0,0,1.76,5.26,6.19,6.19,0,0,0,4.73,1.8,14.83,14.83,0,0,0,3.44-.36,19.71,19.71,0,0,0,3.09-1v2.92a16,16,0,0,1-3.07,1,18.05,18.05,0,0,1-3.61.32,10.7,10.7,0,0,1-5.11-1.18,8.12,8.12,0,0,1-3.45-3.51,12,12,0,0,1-1.24-5.71A13.57,13.57,0,0,1,640,841a8.32,8.32,0,0,1,7.88-5Zm0,2.73a4.83,4.83,0,0,0-3.77,1.54,7.25,7.25,0,0,0-1.66,4.27h10.37a8,8,0,0,0-.53-3,4.49,4.49,0,0,0-1.61-2A4.92,4.92,0,0,0,647.85,838.71Z"
|
||||
id="path23" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M660.08,843.88h9.19V847h-9.19Z"
|
||||
id="path24" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M686.77,856.71l-8.92-23.77h-.15c0,.51.09,1.15.13,1.94s.07,1.64.1,2.56,0,1.87,0,2.83v16.44h-3.15V829.6h5.05l8.36,22.21h.15l8.5-22.21h5v27.11h-3.38V840q0-1.32,0-2.64t.12-2.46c.05-.78.09-1.43.11-2h-.15l-9,23.73Z"
|
||||
id="path25" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M504.76,822.5l-2.52-2.69a16,16,0,0,1,21.51-.37l-2.42,2.77a12.35,12.35,0,0,0-16.57.29Z"
|
||||
id="path27" />
|
||||
<path
|
||||
class="cls-1"
|
||||
d="M509.12,826.65l-2.73-2.47a9.18,9.18,0,0,1,13.18-.45L517,826.38a5.51,5.51,0,0,0-7.9.27Z"
|
||||
id="path28" />
|
||||
<path
|
||||
d="M 727.48499,857.1333 H 709.11 v -3.80989 q 1.91406,-1.64063 3.82812,-3.28125 1.93229,-1.64062 3.59115,-3.26302 3.49999,-3.39062 4.79426,-5.3776 1.29427,-2.0052 1.29427,-4.32031 0,-2.11458 -1.40364,-3.29947 -1.38542,-1.20313 -3.88281,-1.20313 -1.65885,0 -3.59114,0.58334 -1.93229,0.58333 -3.77344,1.78645 h -0.18229 v -3.82812 q 1.29427,-0.63802 3.44531,-1.16666 2.16927,-0.52865 4.19271,-0.52865 4.17447,0 6.54426,2.02344 2.36979,2.0052 2.36979,5.45051 0,1.54948 -0.40104,2.89844 -0.38281,1.33073 -1.14844,2.53385 -0.71093,1.13021 -1.67708,2.22396 -0.94791,1.09375 -2.3151,2.42447 -1.95052,1.91406 -4.02864,3.71875 -2.07813,1.78646 -3.88281,3.31771 h 14.60155 z"
|
||||
id="text1"
|
||||
style="font-size:37.3333px;fill:#262626"
|
||||
aria-label="2" />
|
||||
</g>
|
||||
<g
|
||||
id="Layer_2"
|
||||
data-name="Layer 2">
|
||||
<rect
|
||||
class="cls-5"
|
||||
x="502.29"
|
||||
y="782"
|
||||
width="180.26"
|
||||
height="24.65"
|
||||
rx="12.33"
|
||||
id="rect28" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="515.99"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle28" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="637.4"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle29" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="660.08"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle30" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="539.09"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle31" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="564.93"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle32" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="590.77"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle33" />
|
||||
<circle
|
||||
class="cls-5"
|
||||
cx="614.09"
|
||||
cy="794.33"
|
||||
r="5.48"
|
||||
id="circle34" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M763.35,521.78v329A23.38,23.38,0,0,1,740,874.13H441.22a23.38,23.38,0,0,1-23.38-23.38V456.51a23.38,23.38,0,0,1,23.38-23.38H675.28A18,18,0,0,1,688,438.41L757.66,508A19.43,19.43,0,0,1,763.35,521.78Z"
|
||||
id="path34" />
|
||||
<rect
|
||||
class="cls-7"
|
||||
x="405.9"
|
||||
y="417.86"
|
||||
width="372.52"
|
||||
height="471.54"
|
||||
rx="38.16"
|
||||
id="rect34" />
|
||||
<rect
|
||||
class="cls-8"
|
||||
x="394.16"
|
||||
y="403"
|
||||
width="396"
|
||||
height="501.26"
|
||||
rx="48.72"
|
||||
id="rect35" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M763.35,462.15v30.34a5.64,5.64,0,0,1-9.62,4L700,442.75a5.63,5.63,0,0,1,4-9.62h30.34A29,29,0,0,1,763.35,462.15Z"
|
||||
id="path35" />
|
||||
<rect
|
||||
class="cls-6"
|
||||
x="444.77"
|
||||
y="532.78"
|
||||
width="290.09"
|
||||
height="159.13"
|
||||
rx="18"
|
||||
id="rect36" />
|
||||
<rect
|
||||
class="cls-6"
|
||||
x="454.68"
|
||||
y="541.13"
|
||||
width="268.7"
|
||||
height="139.83"
|
||||
rx="10.7"
|
||||
id="rect37" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M447,904.26v2.94a2,2,0,0,0,2,1.95h14.28a2,2,0,0,0,2-1.95v-2.94"
|
||||
id="path37" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M718.74,904.26v2.94a2,2,0,0,0,2,1.95H735a2,2,0,0,0,2-1.95v-2.94"
|
||||
id="path38" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M790.16,508.83h.39a10.56,10.56,0,0,1,10.56,10.56V656.57a10.56,10.56,0,0,1-10.56,10.56h-.39"
|
||||
id="path39" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M394.16,518.17h-3.31a1.91,1.91,0,0,0-1.91,1.91V797a1.9,1.9,0,0,0,1.91,1.91h3.31"
|
||||
id="path40" />
|
||||
<polyline
|
||||
class="cls-6"
|
||||
points="458.33 403 473.46 384.87 579.68 384.87 595.03 403"
|
||||
id="polyline40" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M579.68,384.87l-.87-21.35a2.51,2.51,0,0,0-2.5-2.39H477.56a2.5,2.5,0,0,0-2.49,2.39l-.87,21.35"
|
||||
id="path41" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M578.32,351.57,577.88,341a2.41,2.41,0,0,0-2.41-2.32H478.41A2.42,2.42,0,0,0,476,341l-.43,10.55a2.42,2.42,0,0,0,2.42,2.52H575.9A2.43,2.43,0,0,0,578.32,351.57Z"
|
||||
id="path42" />
|
||||
<path
|
||||
class="cls-6"
|
||||
d="M476.46,329.56a2,2,0,0,0,2,2.09h96.94a2,2,0,0,0,2-2.09l-7.89-193.08a14.91,14.91,0,0,0-14.9-14.31H499.26a14.91,14.91,0,0,0-14.9,14.31Z"
|
||||
id="path43" />
|
||||
<line
|
||||
class="cls-6"
|
||||
x1="479.53"
|
||||
y1="331.65"
|
||||
x2="479.23"
|
||||
y2="338.7"
|
||||
id="line43" />
|
||||
<line
|
||||
class="cls-6"
|
||||
x1="478.57"
|
||||
y1="354.09"
|
||||
x2="478.26"
|
||||
y2="361.13"
|
||||
id="line44" />
|
||||
<line
|
||||
class="cls-6"
|
||||
x1="574.7"
|
||||
y1="338.7"
|
||||
x2="574.41"
|
||||
y2="331.65"
|
||||
id="line45" />
|
||||
<line
|
||||
class="cls-6"
|
||||
x1="575.63"
|
||||
y1="361.13"
|
||||
x2="575.34"
|
||||
y2="354.09"
|
||||
id="line46" />
|
||||
<polyline
|
||||
class="cls-6"
|
||||
points="491.72 331.65 499.03 137.3 555.9 137.3 561.64 331.65"
|
||||
id="polyline46" />
|
||||
<rect
|
||||
class="cls-8"
|
||||
x="394.16"
|
||||
y="403"
|
||||
width="396"
|
||||
height="501.26"
|
||||
rx="48.72"
|
||||
id="rect46" />
|
||||
<rect
|
||||
class="cls-8"
|
||||
x="394.16"
|
||||
y="403"
|
||||
width="396"
|
||||
height="501.26"
|
||||
rx="48.72"
|
||||
id="rect47" />
|
||||
</g>
|
||||
</svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 14 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 30 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.0 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 30 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 26 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 26 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 6.9 KiB |
|
@ -1,160 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
class="svg-icon"
|
||||
style="overflow:hidden;fill:currentColor"
|
||||
viewBox="0 0 909.87988 546.85529"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
xml:space="preserve"
|
||||
width="909.87988"
|
||||
height="546.85529"
|
||||
sodipodi:docname="unknown.svg"
|
||||
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.57169944"
|
||||
inkscape:cx="291.23695"
|
||||
inkscape:cy="107.57401"
|
||||
inkscape:window-width="1472"
|
||||
inkscape:window-height="890"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="38"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_7" /><defs
|
||||
id="defs3"><style
|
||||
id="style1">.cls-1{fill:#383838;}.cls-2{fill:#9f9f9e;}.cls-3{fill:#cbcccb;}.cls-4{fill:#b7b7b7;}.cls-5{fill:#353535;}.cls-6{fill:#b1a368;}.cls-7{fill:#2c2d2d;}.cls-10,.cls-11,.cls-8,.cls-9{fill:none;stroke:#050606;}.cls-10,.cls-11,.cls-8{stroke-miterlimit:10;}.cls-8,.cls-9{stroke-width:2px;}.cls-9{stroke-linecap:round;stroke-linejoin:round;}.cls-10{stroke-width:2.04px;}.cls-11{stroke-width:1.99px;}.cls-12{fill:#c08c2d;}.cls-13{fill:#af7a2b;}</style></defs><g
|
||||
id="Layer_7"
|
||||
data-name="Layer 7"
|
||||
transform="translate(-646.6554,-758.05941)"><path
|
||||
class="cls-2"
|
||||
d="m 1545.1753,893.49468 h 4.69 a 5.67,5.67 0 0 1 5.67,5.67 v 84.64998 a 5.67,5.67 0 0 1 -5.67,5.67 h -4.69"
|
||||
id="path1-4" /><rect
|
||||
class="cls-3"
|
||||
x="647.6554"
|
||||
y="862.80469"
|
||||
width="897.52002"
|
||||
height="441.10999"
|
||||
rx="11.7"
|
||||
id="rect2" /><path
|
||||
class="cls-2"
|
||||
d="m 681.12532,862.80468 v 113.47998 a 3.67,3.67 0 0 0 3.67,3.67 h 41 a 2.35,2.35 0 0 1 2.35,2.35 V 1303.9147 H 1517.6053 V 862.80468 Z M 1492.6453,1278.9147 H 753.18532 V 972.01466 a 17.06,17.06 0 0 0 -17.06,-17.06 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 h 783.99998 z"
|
||||
id="path2-7" /><path
|
||||
class="cls-3"
|
||||
d="M 1492.6453,887.80468 V 1278.9147 H 753.18532 V 972.01466 a 17,17 0 0 0 -7.2,-13.92 v -70.28998 z"
|
||||
id="path3-7"
|
||||
style="fill:#ffffff" /><path
|
||||
class="cls-4"
|
||||
d="m 745.98532,887.80468 v 70.28998 a 17,17 0 0 0 -9.86,-3.14 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 z"
|
||||
id="path4" /><rect
|
||||
class="cls-2"
|
||||
x="672.10535"
|
||||
y="1011.4448"
|
||||
width="13.53"
|
||||
height="148.39999"
|
||||
id="rect4" /><path
|
||||
class="cls-6"
|
||||
d="m 1077.2923,853.76468 h 71.71 a 2.55,2.55 0 0 1 2.55,2.55 v 6.48 h -76.8 v -6.48 a 2.55,2.55 0 0 1 2.54,-2.55 z"
|
||||
id="path7" /><path
|
||||
class="cls-8"
|
||||
d="m 1082.9205,761.22647 h 60.8838 a 6.1958134,4.8451518 0 0 1 6.1958,4.84516 v 77.32638 h -73.2754 v -77.32638 a 6.1958134,4.8451518 0 0 1 6.1958,-4.84516 z"
|
||||
id="path39"
|
||||
style="fill:#b1a368" /><rect
|
||||
class="cls-8"
|
||||
x="1066.9833"
|
||||
y="778.19855"
|
||||
width="91.504646"
|
||||
height="55.957298"
|
||||
rx="5.5511622"
|
||||
id="rect39"
|
||||
style="fill:#b1a368" /><path
|
||||
class="cls-2"
|
||||
d="m 1158.4522,782.53954 v 47.24724 a 5.5153484,4.3130254 0 0 1 -5.5512,4.34102 h -80.3665 a 5.5511623,4.341032 0 0 1 -5.587,-4.34102 v -47.24724 a 5.5511623,4.341032 0 0 1 5.587,-4.34103 h 80.5098 a 5.5153484,4.3130254 0 0 1 5.4079,4.34103 z"
|
||||
id="path41-4"
|
||||
style="fill:none;stroke:#050606;stroke-width:3.16706;stroke-miterlimit:10" /><rect
|
||||
class="cls-6"
|
||||
x="1079.9424"
|
||||
y="843.73468"
|
||||
width="65.989998"
|
||||
height="10.03"
|
||||
id="rect8" /><path
|
||||
class="cls-8"
|
||||
d="M 1492.6453,887.80468 V 1278.9147 H 753.18532 V 972.01466 a 17.06,17.06 0 0 0 -17.06,-17.06 h -27.5 a 2.5,2.5 0 0 1 -2.5,-2.5 v -62.14998 a 2.5,2.5 0 0 1 2.5,-2.5 h 783.99998 m 25,-25 H 681.12532 v 113.47998 a 3.68,3.68 0 0 0 3.67,3.67 h 41 a 2.35,2.35 0 0 1 2.35,2.35 V 1303.9147 H 1517.6053 V 862.80468 Z"
|
||||
id="path10" /><line
|
||||
class="cls-8"
|
||||
x1="745.99536"
|
||||
y1="958.09467"
|
||||
x2="745.99536"
|
||||
y2="887.80469"
|
||||
id="line10" /><rect
|
||||
class="cls-8"
|
||||
x="672.10535"
|
||||
y="1011.4448"
|
||||
width="13.53"
|
||||
height="148.39999"
|
||||
id="rect11" /><path
|
||||
class="cls-8"
|
||||
d="m 1545.1753,893.49468 h 4.69 a 5.67,5.67 0 0 1 5.67,5.67 v 84.64998 a 5.67,5.67 0 0 1 -5.67,5.67 h -4.69"
|
||||
id="path14" /><path
|
||||
class="cls-10"
|
||||
d="m 1077.2923,853.76468 h 71.71 a 2.55,2.55 0 0 1 2.55,2.55 v 6.48 h -76.8 v -6.48 a 2.55,2.55 0 0 1 2.54,-2.55 z"
|
||||
id="path16" /><rect
|
||||
class="cls-11"
|
||||
x="1079.9424"
|
||||
y="843.73468"
|
||||
width="65.989998"
|
||||
height="10.03"
|
||||
id="rect17" /><path
|
||||
class="cls-2"
|
||||
d="m 725.27532,910.38466 a 14,14 0 1 0 14,14 13.95,13.95 0 0 0 -14,-14 z m 0,21.5 a 7.55,7.55 0 1 1 7.54,-7.55 7.55,7.55 0 0 1 -7.54,7.55 z"
|
||||
id="path19" /><circle
|
||||
class="cls-8"
|
||||
cx="725.27539"
|
||||
cy="924.33466"
|
||||
r="7.5500002"
|
||||
id="circle19" /><circle
|
||||
class="cls-8"
|
||||
cx="725.27539"
|
||||
cy="924.33466"
|
||||
r="13.95"
|
||||
id="circle20" /><path
|
||||
d="m 445.36309,440.05365 c 0,11.52004 10.38375,20.85861 23.19309,20.85861 12.80937,0 23.19311,-9.33857 23.19311,-20.85861 0,-11.52005 -10.38374,-20.85861 -23.19311,-20.85861 -12.80934,0 -23.19309,9.33856 -23.19309,20.85861 z"
|
||||
fill="#ccc"
|
||||
id="path1"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.458227"
|
||||
transform="translate(646.6554,758.05941)" /><path
|
||||
d="m 469.40305,538.40107 c -119.83415,0 -217.31582,-93.40624 -217.31582,-208.23067 0,-114.82425 97.48167,-208.23058 217.31582,-208.23058 119.83417,0 217.31585,93.40633 217.31585,208.23058 0,114.82443 -97.48168,208.23067 -217.31585,208.23067 z m 0,-386.58065 c -102.63515,0 -186.13149,80.00572 -186.13149,178.34998 0,98.32948 83.49634,178.34997 186.13149,178.34997 102.61966,0 186.13151,-80.01997 186.13151,-178.34997 0,-98.34426 -83.51185,-178.34998 -186.13151,-178.34998 z"
|
||||
fill="#ccc"
|
||||
id="path2"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.474832"
|
||||
transform="translate(646.6554,758.05941)" /><path
|
||||
d="m 468.55618,391.96713 c -8.53552,0 -15.46205,-6.22977 -15.46205,-13.90533 v -23.51468 c 0,-22.75028 19.32709,-40.13201 36.39722,-55.47009 12.50833,-11.26363 25.45056,-22.88885 25.45056,-32.16398 0,-23.18095 -20.81195,-42.03718 -46.38573,-42.03718 -26.0067,0 -46.38619,18.0497 -46.38619,41.09158 0,7.67594 -6.92654,13.90533 -15.46208,13.90533 -8.53554,0 -15.46207,-6.22977 -15.46207,-13.9058 0,-37.99002 34.68046,-68.90262 77.31034,-68.90262 42.62989,0 77.31034,31.32967 77.31034,69.84869 0,20.81694 -17.54944,36.5856 -34.51132,51.84064 -13.452,12.07016 -27.33645,24.55758 -27.33645,35.77907 v 23.51468 c 0,7.6764 -6.92702,13.91969 -15.46257,13.91969 z"
|
||||
fill="#ccc"
|
||||
id="path3"
|
||||
style="overflow:hidden;fill:#4d4d4d;stroke-width:0.458227;stroke:#000000;stroke-opacity:1"
|
||||
transform="translate(646.6554,758.05941)" /><rect
|
||||
class="cls-8"
|
||||
x="647.6554"
|
||||
y="862.80469"
|
||||
width="897.52002"
|
||||
height="441.10999"
|
||||
rx="11.7"
|
||||
id="rect28" /></g><path
|
||||
style="fill:#ffffff;fill-opacity:0;stroke-width:0.92"
|
||||
d="m 107.41785,363.03448 -0.23786,-156.30546 -2.99,-3.72057 -2.99,-3.72058 v -34.09394 -34.09394 l 150.64998,0.048 150.64999,0.048 -8.28,3.06943 c -19.31509,7.16019 -34.46167,14.82453 -50.21721,25.41044 -50.57644,33.98158 -84.35747,88.86991 -91.06203,147.96009 -1.43336,12.63279 -0.63536,44.7022 1.3876,55.76392 7.76201,42.44321 25.98398,77.92651 55.67763,108.41989 17.37837,17.84644 33.98994,30.29944 55.42867,41.55255 l 11.30534,5.93414 -134.54212,0.0167 -134.54213,0.0167 z"
|
||||
id="path11" /><path
|
||||
style="fill:#ffffff;fill-opacity:0;stroke-width:0.92"
|
||||
d="m 107.41785,363.03448 -0.23786,-156.30546 -2.99,-3.72057 -2.99,-3.72058 v -34.09394 -34.09394 l 150.64998,0.048 150.64999,0.048 -8.28,3.06943 c -19.31509,7.16019 -34.46167,14.82453 -50.21721,25.41044 -50.57644,33.98158 -84.35747,88.86991 -91.06203,147.96009 -1.43336,12.63279 -0.63536,44.7022 1.3876,55.76392 7.76201,42.44321 25.98398,77.92651 55.67763,108.41989 17.37837,17.84644 33.98994,30.29944 55.42867,41.55255 l 11.30534,5.93414 -134.54212,0.0167 -134.54213,0.0167 z"
|
||||
id="path12" /><path
|
||||
style="fill:#ffffff;fill-opacity:0;stroke-width:0.92"
|
||||
d="m 107.41785,363.03448 -0.23786,-156.30546 -2.99,-3.72057 -2.99,-3.72058 v -34.09394 -34.09394 l 150.64998,0.048 150.64999,0.048 -8.28,3.06943 c -19.31509,7.16019 -34.46167,14.82453 -50.21721,25.41044 -50.57644,33.98158 -84.35747,88.86991 -91.06203,147.96009 -1.43336,12.63279 -0.63536,44.7022 1.3876,55.76392 7.76201,42.44321 25.98398,77.92651 55.67763,108.41989 17.37837,17.84644 33.98994,30.29944 55.42867,41.55255 l 11.30534,5.93414 -134.54212,0.0167 -134.54213,0.0167 z"
|
||||
id="path13" /></svg>
|
Przed Szerokość: | Wysokość: | Rozmiar: 9.1 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 91 KiB |
Przed Szerokość: | Wysokość: | Rozmiar: 120 KiB |
|
@ -35,7 +35,8 @@ data class MyNodeInfo(
|
|||
val maxChannels: Int,
|
||||
val hasWifi: Boolean,
|
||||
val channelUtilization: Float,
|
||||
val airUtilTx: Float
|
||||
val airUtilTx: Float,
|
||||
val deviceId: String?,
|
||||
) : Parcelable {
|
||||
/** A human readable description of the software/hardware version */
|
||||
val firmwareString: String get() = "$model $firmwareVersion"
|
||||
|
|
|
@ -129,4 +129,20 @@ class Converters : Logging {
|
|||
fun metadataToBytes(value: MeshProtos.DeviceMetadata): ByteArray? {
|
||||
return value.toByteArray()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromStringList(value: String?): List<String>? {
|
||||
if (value == null) {
|
||||
return null
|
||||
}
|
||||
return Json.decodeFromString<List<String>>(value)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toStringList(list: List<String>?): String? {
|
||||
if (list == null) {
|
||||
return null
|
||||
}
|
||||
return Json.encodeToString(list)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
package com.geeksville.mesh.database
|
||||
|
||||
import android.app.Application
|
||||
import com.geeksville.mesh.database.dao.DeviceHardwareDao
|
||||
import com.geeksville.mesh.database.dao.FirmwareReleaseDao
|
||||
import com.geeksville.mesh.database.dao.MeshLogDao
|
||||
import com.geeksville.mesh.database.dao.NodeInfoDao
|
||||
import com.geeksville.mesh.database.dao.PacketDao
|
||||
|
@ -55,4 +57,14 @@ class DatabaseModule {
|
|||
fun provideQuickChatActionDao(database: MeshtasticDatabase): QuickChatActionDao {
|
||||
return database.quickChatActionDao()
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideDeviceHardwareDao(database: MeshtasticDatabase): DeviceHardwareDao {
|
||||
return database.deviceHardwareDao()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideFirmwareReleaseDao(database: MeshtasticDatabase): FirmwareReleaseDao {
|
||||
return database.firmwareReleaseDao()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,15 @@ import androidx.room.Room
|
|||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.AutoMigrationSpec
|
||||
import com.geeksville.mesh.database.dao.PacketDao
|
||||
import com.geeksville.mesh.database.dao.DeviceHardwareDao
|
||||
import com.geeksville.mesh.database.dao.FirmwareReleaseDao
|
||||
import com.geeksville.mesh.database.dao.MeshLogDao
|
||||
import com.geeksville.mesh.database.dao.NodeInfoDao
|
||||
import com.geeksville.mesh.database.dao.PacketDao
|
||||
import com.geeksville.mesh.database.dao.QuickChatActionDao
|
||||
import com.geeksville.mesh.database.entity.ContactSettings
|
||||
import com.geeksville.mesh.database.entity.DeviceHardwareEntity
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseEntity
|
||||
import com.geeksville.mesh.database.entity.MeshLog
|
||||
import com.geeksville.mesh.database.entity.MetadataEntity
|
||||
import com.geeksville.mesh.database.entity.MyNodeEntity
|
||||
|
@ -48,6 +52,8 @@ import com.geeksville.mesh.database.entity.ReactionEntity
|
|||
QuickChatAction::class,
|
||||
ReactionEntity::class,
|
||||
MetadataEntity::class,
|
||||
DeviceHardwareEntity::class,
|
||||
FirmwareReleaseEntity::class,
|
||||
],
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 3, to = 4),
|
||||
|
@ -63,8 +69,9 @@ import com.geeksville.mesh.database.entity.ReactionEntity
|
|||
AutoMigration(from = 13, to = 14),
|
||||
AutoMigration(from = 14, to = 15),
|
||||
AutoMigration(from = 15, to = 16),
|
||||
AutoMigration(from = 16, to = 17),
|
||||
],
|
||||
version = 16,
|
||||
version = 17,
|
||||
exportSchema = true,
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
|
@ -73,6 +80,8 @@ abstract class MeshtasticDatabase : RoomDatabase() {
|
|||
abstract fun packetDao(): PacketDao
|
||||
abstract fun meshLogDao(): MeshLogDao
|
||||
abstract fun quickChatActionDao(): QuickChatActionDao
|
||||
abstract fun deviceHardwareDao(): DeviceHardwareDao
|
||||
abstract fun firmwareReleaseDao(): FirmwareReleaseDao
|
||||
|
||||
companion object {
|
||||
fun getDatabase(context: Context): MeshtasticDatabase {
|
||||
|
@ -82,7 +91,7 @@ abstract class MeshtasticDatabase : RoomDatabase() {
|
|||
MeshtasticDatabase::class.java,
|
||||
"meshtastic_database"
|
||||
)
|
||||
.fallbackToDestructiveMigration()
|
||||
.fallbackToDestructiveMigration(false)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.geeksville.mesh.database.entity.DeviceHardwareEntity
|
||||
|
||||
@Dao
|
||||
interface DeviceHardwareDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(deviceHardware: DeviceHardwareEntity)
|
||||
|
||||
@Query("SELECT * FROM device_hardware WHERE hwModel = :hwModel")
|
||||
suspend fun getByHwModel(hwModel: Int): DeviceHardwareEntity?
|
||||
|
||||
@Query("DELETE FROM device_hardware")
|
||||
suspend fun deleteAll()
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseEntity
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseType
|
||||
|
||||
@Dao
|
||||
interface FirmwareReleaseDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(firmwareReleaseEntity: FirmwareReleaseEntity)
|
||||
|
||||
@Query("DELETE FROM firmware_release")
|
||||
suspend fun deleteAll()
|
||||
|
||||
@Query("SELECT * FROM firmware_release")
|
||||
suspend fun getAllReleases(): List<FirmwareReleaseEntity>?
|
||||
|
||||
@Query("SELECT * FROM firmware_release WHERE release_type = :releaseType")
|
||||
suspend fun getReleasesByType(releaseType: FirmwareReleaseType): List<FirmwareReleaseEntity>?
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.database.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.geeksville.mesh.model.DeviceHardware
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Entity(tableName = "device_hardware")
|
||||
data class DeviceHardwareEntity(
|
||||
@ColumnInfo(name = "actively_supported") val activelySupported: Boolean,
|
||||
val architecture: String,
|
||||
@ColumnInfo(name = "display_name") val displayName: String,
|
||||
@ColumnInfo(name = "has_ink_hud") val hasInkHud: Boolean? = null,
|
||||
@ColumnInfo(name = "has_mui") val hasMui: Boolean? = null,
|
||||
@PrimaryKey val hwModel: Int,
|
||||
@ColumnInfo(name = "hw_model_slug") val hwModelSlug: String,
|
||||
val images: List<String>?,
|
||||
@ColumnInfo(name = "last_updated") val lastUpdated: Long = System.currentTimeMillis(),
|
||||
@ColumnInfo(name = "partition_scheme") val partitionScheme: String? = null,
|
||||
@ColumnInfo(name = "platformio_target") val platformioTarget: String,
|
||||
@ColumnInfo(name = "requires_dfu") val requiresDfu: Boolean?,
|
||||
@ColumnInfo(name = "support_level") val supportLevel: Int?,
|
||||
val tags: List<String>?,
|
||||
)
|
||||
|
||||
fun NetworkDeviceHardware.asEntity() = DeviceHardwareEntity(
|
||||
activelySupported = activelySupported,
|
||||
architecture = architecture,
|
||||
displayName = displayName,
|
||||
hasInkHud = hasInkHud,
|
||||
hasMui = hasMui,
|
||||
hwModel = hwModel,
|
||||
hwModelSlug = hwModelSlug,
|
||||
images = images,
|
||||
lastUpdated = System.currentTimeMillis(),
|
||||
partitionScheme = partitionScheme,
|
||||
platformioTarget = platformioTarget,
|
||||
requiresDfu = requiresDfu,
|
||||
supportLevel = supportLevel,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
fun DeviceHardwareEntity.asExternalModel() = DeviceHardware(
|
||||
activelySupported = activelySupported,
|
||||
architecture = architecture,
|
||||
displayName = displayName,
|
||||
hasInkHud = hasInkHud,
|
||||
hasMui = hasMui,
|
||||
hwModel = hwModel,
|
||||
hwModelSlug = hwModelSlug,
|
||||
images = images,
|
||||
partitionScheme = partitionScheme,
|
||||
platformioTarget = platformioTarget,
|
||||
requiresDfu = requiresDfu,
|
||||
supportLevel = supportLevel,
|
||||
tags = tags,
|
||||
)
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.database.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareRelease
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Entity(tableName = "firmware_release")
|
||||
data class FirmwareReleaseEntity(
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = "id")
|
||||
val id: String = "",
|
||||
@ColumnInfo(name = "page_url")
|
||||
val pageUrl: String = "",
|
||||
@ColumnInfo(name = "release_notes")
|
||||
val releaseNotes: String = "",
|
||||
@ColumnInfo(name = "title")
|
||||
val title: String = "",
|
||||
@ColumnInfo(name = "zip_url")
|
||||
val zipUrl: String = "",
|
||||
@ColumnInfo(name = "last_updated")
|
||||
val lastUpdated: Long = System.currentTimeMillis(),
|
||||
@ColumnInfo(name = "release_type")
|
||||
val releaseType: FirmwareReleaseType = FirmwareReleaseType.STABLE,
|
||||
)
|
||||
|
||||
fun NetworkFirmwareRelease.asEntity(releaseType: FirmwareReleaseType) = FirmwareReleaseEntity(
|
||||
id = id,
|
||||
pageUrl = pageUrl,
|
||||
releaseNotes = releaseNotes,
|
||||
title = title,
|
||||
zipUrl = zipUrl,
|
||||
lastUpdated = System.currentTimeMillis(),
|
||||
releaseType = releaseType,
|
||||
)
|
||||
|
||||
fun FirmwareReleaseEntity.asExternalModel() = FirmwareRelease(
|
||||
id = id,
|
||||
pageUrl = pageUrl,
|
||||
releaseNotes = releaseNotes,
|
||||
title = title,
|
||||
zipUrl = zipUrl,
|
||||
lastUpdated = lastUpdated,
|
||||
releaseType = releaseType,
|
||||
)
|
||||
|
||||
data class FirmwareRelease(
|
||||
val id: String = "",
|
||||
val pageUrl: String = "",
|
||||
val releaseNotes: String = "",
|
||||
val title: String = "",
|
||||
val zipUrl: String = "",
|
||||
val lastUpdated: Long = System.currentTimeMillis(),
|
||||
val releaseType: FirmwareReleaseType = FirmwareReleaseType.STABLE,
|
||||
)
|
||||
|
||||
enum class FirmwareReleaseType {
|
||||
STABLE,
|
||||
ALPHA
|
||||
}
|
|
@ -34,6 +34,7 @@ data class MyNodeEntity(
|
|||
val minAppVersion: Int,
|
||||
val maxChannels: Int,
|
||||
val hasWifi: Boolean,
|
||||
val deviceId: String? = "unknown",
|
||||
) {
|
||||
/** A human readable description of the software/hardware version */
|
||||
val firmwareString: String get() = "$model $firmwareVersion"
|
||||
|
@ -52,5 +53,6 @@ data class MyNodeEntity(
|
|||
hasWifi = hasWifi,
|
||||
channelUtilization = 0f,
|
||||
airUtilTx = 0f,
|
||||
deviceId = deviceId,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import androidx.lifecycle.viewModelScope
|
|||
import androidx.navigation.toRoute
|
||||
import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig.DisplayUnits
|
||||
import com.geeksville.mesh.CoroutineDispatchers
|
||||
import com.geeksville.mesh.MeshProtos.HardwareModel
|
||||
import com.geeksville.mesh.MeshProtos.MeshPacket
|
||||
import com.geeksville.mesh.MeshProtos.Position
|
||||
import com.geeksville.mesh.Portnums.PortNum
|
||||
|
@ -37,9 +36,12 @@ import com.geeksville.mesh.R
|
|||
import com.geeksville.mesh.TelemetryProtos.Telemetry
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import com.geeksville.mesh.database.MeshLogRepository
|
||||
import com.geeksville.mesh.database.entity.FirmwareRelease
|
||||
import com.geeksville.mesh.database.entity.MeshLog
|
||||
import com.geeksville.mesh.model.map.CustomTileSource
|
||||
import com.geeksville.mesh.navigation.Route
|
||||
import com.geeksville.mesh.repository.api.DeviceHardwareRepository
|
||||
import com.geeksville.mesh.repository.api.FirmwareReleaseRepository
|
||||
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
|
||||
import com.geeksville.mesh.service.ServiceAction
|
||||
import com.geeksville.mesh.ui.map.MAP_STYLE_ID
|
||||
|
@ -56,11 +58,9 @@ import kotlinx.coroutines.flow.toList
|
|||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.BufferedWriter
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -79,6 +79,9 @@ data class MetricsState(
|
|||
val tracerouteResults: List<MeshPacket> = emptyList(),
|
||||
val positionLogs: List<Position> = emptyList(),
|
||||
val deviceHardware: DeviceHardware? = null,
|
||||
val isLocalDevice: Boolean = false,
|
||||
val latestStableFirmware: FirmwareRelease? = null,
|
||||
val latestAlphaFirmware: FirmwareRelease? = null,
|
||||
) {
|
||||
fun hasDeviceMetrics() = deviceMetrics.isNotEmpty()
|
||||
fun hasSignalMetrics() = signalMetrics.isNotEmpty()
|
||||
|
@ -188,6 +191,7 @@ private fun MeshPacket.toPosition(): Position? = if (!decoded.wantResponse) {
|
|||
null
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@HiltViewModel
|
||||
class MetricsViewModel @Inject constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
|
@ -195,6 +199,8 @@ class MetricsViewModel @Inject constructor(
|
|||
private val dispatchers: CoroutineDispatchers,
|
||||
private val meshLogRepository: MeshLogRepository,
|
||||
private val radioConfigRepository: RadioConfigRepository,
|
||||
private val deviceHardwareRepository: DeviceHardwareRepository,
|
||||
private val firmwareReleaseRepository: FirmwareReleaseRepository,
|
||||
private val preferences: SharedPreferences,
|
||||
) : ViewModel(), Logging {
|
||||
private val destNum = savedStateHandle.toRoute<Route.NodeDetail>().destNum
|
||||
|
@ -229,25 +235,23 @@ class MetricsViewModel @Inject constructor(
|
|||
private val _timeFrame = MutableStateFlow(TimeFrame.TWENTY_FOUR_HOURS)
|
||||
val timeFrame: StateFlow<TimeFrame> = _timeFrame
|
||||
|
||||
private var deviceHardwareList: List<DeviceHardware> = listOf()
|
||||
|
||||
init {
|
||||
destNum?.let {
|
||||
radioConfigRepository.nodeDBbyNum
|
||||
.mapLatest { nodes -> nodes[destNum] to nodes.keys.firstOrNull() }
|
||||
.distinctUntilChanged()
|
||||
.onEach { (node, ourNode) ->
|
||||
_state.update { state -> state.copy(node = node, isLocal = destNum == ourNode) }
|
||||
node?.user?.hwModel?.let { hwModel ->
|
||||
val deviceHardware = getDeviceHardwareFromHardwareModel(hwModel)
|
||||
deviceHardware?.let {
|
||||
_state.update { state ->
|
||||
state.copy(deviceHardware = it)
|
||||
}
|
||||
}
|
||||
val deviceHardware = node?.user?.hwModel?.number?.let {
|
||||
deviceHardwareRepository.getDeviceHardwareByModel(it)
|
||||
}
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
_state.update { state ->
|
||||
state.copy(
|
||||
node = node,
|
||||
isLocal = destNum == ourNode,
|
||||
deviceHardware = deviceHardware
|
||||
)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
radioConfigRepository.deviceProfileFlow.onEach { profile ->
|
||||
val moduleConfig = profile.moduleConfig
|
||||
|
@ -308,6 +312,18 @@ class MetricsViewModel @Inject constructor(
|
|||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
firmwareReleaseRepository.stableRelease.onEach { latestStable ->
|
||||
_state.update { state ->
|
||||
state.copy(latestStableFirmware = latestStable)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
firmwareReleaseRepository.alphaRelease.onEach { latestAlpha ->
|
||||
_state.update { state ->
|
||||
state.copy(latestAlphaFirmware = latestAlpha)
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
debug("MetricsViewModel created")
|
||||
}
|
||||
}
|
||||
|
@ -361,22 +377,4 @@ class MetricsViewModel @Inject constructor(
|
|||
errormsg("Can't write file error: ${ex.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeviceHardwareFromHardwareModel(
|
||||
hwModel: HardwareModel
|
||||
): DeviceHardware? {
|
||||
if (deviceHardwareList.isEmpty()) {
|
||||
try {
|
||||
val json =
|
||||
app.assets.open("device_hardware.json").bufferedReader().use { it.readText() }
|
||||
deviceHardwareList = Json.decodeFromString<List<DeviceHardware>>(json)
|
||||
return deviceHardwareList.find { it.hwModel == hwModel.number }
|
||||
} catch (ex: IOException) {
|
||||
errormsg("Can't read device_hardware.json error: ${ex.message}")
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
errormsg(ex.message.toString())
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import android.app.Application
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceHardwareJsonDataSource @Inject constructor(
|
||||
private val application: Application,
|
||||
) {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun loadDeviceHardwareFromJsonAsset(): List<NetworkDeviceHardware> {
|
||||
val inputStream = application.assets.open("device_hardware.json")
|
||||
return Json.decodeFromStream<List<NetworkDeviceHardware>>(inputStream)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import com.geeksville.mesh.database.dao.DeviceHardwareDao
|
||||
import com.geeksville.mesh.database.entity.DeviceHardwareEntity
|
||||
import com.geeksville.mesh.database.entity.asEntity
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceHardwareLocalDataSource @Inject constructor(
|
||||
private val deviceHardwareDaoLazy: dagger.Lazy<DeviceHardwareDao>
|
||||
) {
|
||||
private val deviceHardwareDao by lazy {
|
||||
deviceHardwareDaoLazy.get()
|
||||
}
|
||||
|
||||
suspend fun insertAllDeviceHardware(deviceHardware: List<NetworkDeviceHardware>) =
|
||||
withContext(Dispatchers.IO) {
|
||||
deviceHardware.forEach { deviceHardware ->
|
||||
deviceHardwareDao.insert(deviceHardware.asEntity())
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteAllDeviceHardware() = withContext(Dispatchers.IO) {
|
||||
deviceHardwareDao.deleteAll()
|
||||
}
|
||||
|
||||
suspend fun getByHwModel(hwModel: Int): DeviceHardwareEntity? = withContext(Dispatchers.IO) {
|
||||
deviceHardwareDao.getByHwModel(hwModel)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.android.BuildUtils.warn
|
||||
import com.geeksville.mesh.database.entity.asExternalModel
|
||||
import com.geeksville.mesh.model.DeviceHardware
|
||||
import com.geeksville.mesh.network.DeviceHardwareRemoteDataSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceHardwareRepository @Inject constructor(
|
||||
private val apiDataSource: DeviceHardwareRemoteDataSource,
|
||||
private val localDataSource: DeviceHardwareLocalDataSource,
|
||||
private val jsonDataSource: DeviceHardwareJsonDataSource,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
// 1 day
|
||||
private const val CACHE_EXPIRATION_TIME_MS = 24 * 60 * 60 * 1000L
|
||||
}
|
||||
|
||||
suspend fun getDeviceHardwareByModel(hwModel: Int, refresh: Boolean = false): DeviceHardware? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
if (refresh) {
|
||||
invalidateCache()
|
||||
} else {
|
||||
val cachedHardware = localDataSource.getByHwModel(hwModel)
|
||||
if (cachedHardware != null && !isCacheExpired(cachedHardware.lastUpdated)) {
|
||||
debug("Using recent cached device hardware")
|
||||
val externalModel = cachedHardware.asExternalModel()
|
||||
return@withContext externalModel
|
||||
}
|
||||
}
|
||||
try {
|
||||
debug("Fetching device hardware from server")
|
||||
localDataSource.insertAllDeviceHardware(apiDataSource.getAllDeviceHardware())
|
||||
val cachedHardware = localDataSource.getByHwModel(hwModel)
|
||||
val externalModel = cachedHardware?.asExternalModel()
|
||||
return@withContext externalModel
|
||||
} catch (e: IOException) {
|
||||
warn("Failed to fetch device hardware from server: ${e.message}")
|
||||
var cachedHardware = localDataSource.getByHwModel(hwModel)
|
||||
if (cachedHardware != null) {
|
||||
debug("Using stale cached device hardware")
|
||||
return@withContext cachedHardware.asExternalModel()
|
||||
}
|
||||
debug("Loading and caching device hardware from local JSON asset")
|
||||
localDataSource.insertAllDeviceHardware(jsonDataSource.loadDeviceHardwareFromJsonAsset())
|
||||
cachedHardware = localDataSource.getByHwModel(hwModel)
|
||||
val externalModel = cachedHardware?.asExternalModel()
|
||||
return@withContext externalModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun invalidateCache() {
|
||||
localDataSource.deleteAllDeviceHardware()
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cache is expired
|
||||
*/
|
||||
private fun isCacheExpired(lastUpdated: Long): Boolean {
|
||||
return System.currentTimeMillis() - lastUpdated > CACHE_EXPIRATION_TIME_MS
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import android.app.Application
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirmwareReleaseJsonDataSource @Inject constructor(
|
||||
private val application: Application,
|
||||
) {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun loadFirmwareReleaseFromJsonAsset(): NetworkFirmwareReleases {
|
||||
val inputStream = application.assets.open("firmware_releases.json")
|
||||
val result = inputStream.use {
|
||||
Json.decodeFromStream<NetworkFirmwareReleases>(inputStream)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import com.geeksville.mesh.database.dao.FirmwareReleaseDao
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseEntity
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseType
|
||||
import com.geeksville.mesh.database.entity.asEntity
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareRelease
|
||||
import dagger.Lazy
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirmwareReleaseLocalDataSource @Inject constructor(
|
||||
private val firmwareReleaseDaoLazy: Lazy<FirmwareReleaseDao>
|
||||
) {
|
||||
private val firmwareReleaseDao by lazy {
|
||||
firmwareReleaseDaoLazy.get()
|
||||
}
|
||||
|
||||
suspend fun insertFirmwareReleases(
|
||||
firmwareReleases: List<NetworkFirmwareRelease>,
|
||||
releaseType: FirmwareReleaseType
|
||||
) =
|
||||
withContext(Dispatchers.IO) {
|
||||
firmwareReleases.forEach { firmwareRelease ->
|
||||
firmwareReleaseDao.insert(firmwareRelease.asEntity(releaseType))
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteAllFirmwareReleases() = withContext(Dispatchers.IO) {
|
||||
firmwareReleaseDao.deleteAll()
|
||||
}
|
||||
|
||||
suspend fun getLatestRelease(releaseType: FirmwareReleaseType): FirmwareReleaseEntity? =
|
||||
withContext(Dispatchers.IO) {
|
||||
val releases = firmwareReleaseDao.getReleasesByType(releaseType)
|
||||
val latestRelease =
|
||||
releases?.firstOrNull()
|
||||
return@withContext latestRelease
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.repository.api
|
||||
|
||||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.android.BuildUtils.warn
|
||||
import com.geeksville.mesh.database.entity.FirmwareRelease
|
||||
import com.geeksville.mesh.database.entity.FirmwareReleaseType
|
||||
import com.geeksville.mesh.database.entity.asExternalModel
|
||||
import com.geeksville.mesh.network.FirmwareReleaseRemoteDataSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirmwareReleaseRepository @Inject constructor(
|
||||
private val apiDataSource: FirmwareReleaseRemoteDataSource,
|
||||
private val localDataSource: FirmwareReleaseLocalDataSource,
|
||||
private val jsonDataSource: FirmwareReleaseJsonDataSource,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
// 1 hour
|
||||
private const val CACHE_EXPIRATION_TIME_MS = 60 * 60 * 1000L
|
||||
}
|
||||
|
||||
val stableRelease: Flow<FirmwareRelease?> = getLatestFirmware(FirmwareReleaseType.STABLE)
|
||||
|
||||
val alphaRelease: Flow<FirmwareRelease?> = getLatestFirmware(FirmwareReleaseType.ALPHA)
|
||||
|
||||
private fun getLatestFirmware(
|
||||
releaseType: FirmwareReleaseType,
|
||||
refresh: Boolean = false
|
||||
): Flow<FirmwareRelease?> = flow {
|
||||
if (refresh) {
|
||||
invalidateCache()
|
||||
} else {
|
||||
val cachedRelease = localDataSource.getLatestRelease(releaseType)
|
||||
if (cachedRelease != null && !isCacheExpired(cachedRelease.lastUpdated)) {
|
||||
debug("Using recent cached firmware release")
|
||||
val externalModel = cachedRelease.asExternalModel()
|
||||
emit(externalModel)
|
||||
return@flow
|
||||
}
|
||||
}
|
||||
try {
|
||||
debug("Fetching firmware releases from server")
|
||||
val networkFirmwareReleases = apiDataSource.getFirmwareReleases()
|
||||
val releases = when (releaseType) {
|
||||
FirmwareReleaseType.STABLE -> networkFirmwareReleases.releases.stable
|
||||
FirmwareReleaseType.ALPHA -> networkFirmwareReleases.releases.alpha
|
||||
}
|
||||
localDataSource.insertFirmwareReleases(
|
||||
releases,
|
||||
releaseType
|
||||
)
|
||||
val cachedRelease = localDataSource.getLatestRelease(releaseType)
|
||||
val externalModel = cachedRelease?.asExternalModel()
|
||||
emit(externalModel)
|
||||
} catch (e: IOException) {
|
||||
warn("Failed to fetch firmware releases from server: ${e.message}")
|
||||
val jsonFirmwareReleases = jsonDataSource.loadFirmwareReleaseFromJsonAsset()
|
||||
val releases = when (releaseType) {
|
||||
FirmwareReleaseType.STABLE -> jsonFirmwareReleases.releases.stable
|
||||
FirmwareReleaseType.ALPHA -> jsonFirmwareReleases.releases.alpha
|
||||
}
|
||||
localDataSource.insertFirmwareReleases(
|
||||
releases,
|
||||
releaseType
|
||||
)
|
||||
val cachedRelease = localDataSource.getLatestRelease(releaseType)
|
||||
val externalModel = cachedRelease?.asExternalModel()
|
||||
emit(externalModel)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun invalidateCache() {
|
||||
localDataSource.deleteAllFirmwareReleases()
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the cache is expired
|
||||
*/
|
||||
private fun isCacheExpired(lastUpdated: Long): Boolean {
|
||||
return System.currentTimeMillis() - lastUpdated > CACHE_EXPIRATION_TIME_MS
|
||||
}
|
||||
}
|
|
@ -1604,6 +1604,7 @@ class MeshService : Service(), Logging {
|
|||
minAppVersion = minAppVersion,
|
||||
maxChannels = 8,
|
||||
hasWifi = metadata.hasWifi,
|
||||
deviceId = deviceId.toStringUtf8(),
|
||||
)
|
||||
}
|
||||
serviceScope.handledLaunch {
|
||||
|
|
|
@ -57,11 +57,11 @@ import androidx.compose.material.icons.filled.Share
|
|||
import androidx.compose.material.icons.filled.SignalCellularAlt
|
||||
import androidx.compose.material.icons.filled.Speed
|
||||
import androidx.compose.material.icons.filled.Thermostat
|
||||
import androidx.compose.material.icons.filled.Verified
|
||||
import androidx.compose.material.icons.filled.WaterDrop
|
||||
import androidx.compose.material.icons.filled.Work
|
||||
import androidx.compose.material.icons.outlined.Navigation
|
||||
import androidx.compose.material.icons.outlined.NoCell
|
||||
import androidx.compose.material.icons.twotone.Verified
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
|
@ -79,6 +79,7 @@ import androidx.compose.ui.draw.rotate
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
|
@ -90,7 +91,11 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.request.ErrorResult
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.request.SuccessResult
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.model.DeviceHardware
|
||||
import com.geeksville.mesh.model.MetricsState
|
||||
import com.geeksville.mesh.model.MetricsViewModel
|
||||
|
@ -207,6 +212,33 @@ private fun NodeDetailList(
|
|||
NodeDetailsContent(node)
|
||||
}
|
||||
}
|
||||
node.metadata?.firmwareVersion?.let { firmwareVersion ->
|
||||
item {
|
||||
PreferenceCategory(stringResource(R.string.firmware)) {
|
||||
val latestStableFirmware = metricsState.latestStableFirmware
|
||||
val latestAlphaFirmware = metricsState.latestAlphaFirmware
|
||||
NodeDetailRow(
|
||||
label = "Installed",
|
||||
icon = Icons.Default.Memory,
|
||||
value = firmwareVersion.substringBeforeLast(".")
|
||||
)
|
||||
latestStableFirmware?.let { stable ->
|
||||
NodeDetailRow(
|
||||
label = "Latest stable",
|
||||
icon = Icons.Default.Memory,
|
||||
value = stable.id.substringBeforeLast(".").replace("v", "")
|
||||
)
|
||||
}
|
||||
latestAlphaFirmware?.let { alpha ->
|
||||
NodeDetailRow(
|
||||
label = "Latest alpha",
|
||||
icon = Icons.Default.Memory,
|
||||
value = alpha.id.substringBeforeLast(".").replace("v", "")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
DeviceActions(
|
||||
|
@ -332,25 +364,19 @@ private fun DeviceDetailsContent(
|
|||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
DeviceHardwareImage(
|
||||
deviceHardware = deviceHardware,
|
||||
modifier = Modifier
|
||||
.size(100.dp)
|
||||
)
|
||||
DeviceHardwareImage(deviceHardware, Modifier.fillMaxSize())
|
||||
}
|
||||
NodeDetailRow(
|
||||
label = stringResource(R.string.hardware),
|
||||
icon = Icons.Default.Router,
|
||||
value = hwModelName
|
||||
)
|
||||
if (isSupported) {
|
||||
NodeDetailRow(
|
||||
label = stringResource(R.string.supported),
|
||||
icon = Icons.Default.Verified,
|
||||
value = "",
|
||||
iconTint = Color.Green
|
||||
)
|
||||
}
|
||||
NodeDetailRow(
|
||||
label = if (isSupported) stringResource(R.string.supported) else "Supported by Community",
|
||||
icon = if (isSupported) Icons.TwoTone.Verified else ImageVector.vectorResource(R.drawable.unverified),
|
||||
value = "",
|
||||
iconTint = if (isSupported) Color.Green else Color.Red
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -358,20 +384,37 @@ fun DeviceHardwareImage(
|
|||
deviceHardware: DeviceHardware,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hwImg = deviceHardware.images?.lastOrNull()
|
||||
if (hwImg != null) {
|
||||
val imageUrl = "file:///android_asset/device_hardware/$hwImg"
|
||||
AsyncImage(
|
||||
model = imageUrl,
|
||||
contentScale = ContentScale.Inside,
|
||||
contentDescription = deviceHardware.displayName,
|
||||
placeholder = painterResource(R.drawable.hw_unknown),
|
||||
error = painterResource(R.drawable.hw_unknown),
|
||||
fallback = painterResource(R.drawable.hw_unknown),
|
||||
modifier = modifier
|
||||
.padding(16.dp)
|
||||
)
|
||||
val hwImg = deviceHardware.images?.get(1) ?: deviceHardware.images?.get(0) ?: "unknown.svg"
|
||||
val imageUrl = "https://flasher.meshtastic.org/img/devices/$hwImg"
|
||||
val listener = object : ImageRequest.Listener {
|
||||
override fun onStart(request: ImageRequest) {
|
||||
super.onStart(request)
|
||||
debug("Image request started")
|
||||
}
|
||||
|
||||
override fun onError(request: ImageRequest, result: ErrorResult) {
|
||||
super.onError(request, result)
|
||||
debug("Image request failed: ${result.throwable.message}")
|
||||
}
|
||||
|
||||
override fun onSuccess(request: ImageRequest, result: SuccessResult) {
|
||||
super.onSuccess(request, result)
|
||||
debug("Image request succeeded: ${result.dataSource.name}")
|
||||
}
|
||||
}
|
||||
AsyncImage(
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.listener(listener)
|
||||
.data(imageUrl)
|
||||
.build(),
|
||||
contentScale = ContentScale.Inside,
|
||||
contentDescription = deviceHardware.displayName,
|
||||
placeholder = painterResource(R.drawable.hw_unknown),
|
||||
error = painterResource(R.drawable.hw_unknown),
|
||||
fallback = painterResource(R.drawable.hw_unknown),
|
||||
modifier = modifier
|
||||
.padding(16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
|
@ -435,13 +478,6 @@ private fun NodeDetailsContent(
|
|||
value = formatUptime(node.deviceMetrics.uptimeSeconds)
|
||||
)
|
||||
}
|
||||
if (node.metadata != null) {
|
||||
NodeDetailRow(
|
||||
label = stringResource(R.string.firmware_version),
|
||||
icon = Icons.Default.Memory,
|
||||
value = node.metadata.firmwareVersion.substringBeforeLast(".")
|
||||
)
|
||||
}
|
||||
NodeDetailRow(
|
||||
label = stringResource(R.string.node_sort_last_heard),
|
||||
icon = Icons.Default.History,
|
||||
|
|
|
@ -1,138 +1,121 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="909.9dp"
|
||||
android:height="1044.4dp"
|
||||
android:viewportWidth="909.9"
|
||||
android:viewportHeight="1044.4">
|
||||
android:width="909.88dp"
|
||||
android:height="546.86dp"
|
||||
android:viewportWidth="909.88"
|
||||
android:viewportHeight="546.86">
|
||||
<path
|
||||
android:pathData="m898.5,633h4.7a5.7,5.7 0,0 1,5.7 5.7v84.6a5.7,5.7 0,0 1,-5.7 5.7h-4.7"
|
||||
android:pathData="m898.52,135.44h4.69a5.67,5.67 0,0 1,5.67 5.67v84.65a5.67,5.67 0,0 1,-5.67 5.67h-4.69"
|
||||
android:fillColor="#9f9f9e"/>
|
||||
<path
|
||||
android:pathData="M12.7,602.3L886.8,602.3A11.7,11.7 0,0 1,898.5 614L898.5,1031.7A11.7,11.7 0,0 1,886.8 1043.4L12.7,1043.4A11.7,11.7 0,0 1,1 1031.7L1,614A11.7,11.7 0,0 1,12.7 602.3z"
|
||||
android:pathData="M12.7,104.75L886.82,104.75A11.7,11.7 0,0 1,898.52 116.45L898.52,534.16A11.7,11.7 0,0 1,886.82 545.86L12.7,545.86A11.7,11.7 0,0 1,1 534.16L1,116.45A11.7,11.7 0,0 1,12.7 104.75z"
|
||||
android:fillColor="#cbcccb"/>
|
||||
<path
|
||||
android:pathData="m34.5,602.3v113.5a3.7,3.7 0,0 0,3.7 3.7h41a2.3,2.3 0,0 1,2.3 2.3L81.5,1043.4L870.9,1043.4L870.9,602.3ZM846,1018.4L106.5,1018.4L106.5,711.5a17.1,17.1 0,0 0,-17.1 -17.1h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.1a2.5,2.5 0,0 1,2.5 -2.5h784z"
|
||||
android:pathData="m34.47,104.75v113.48a3.67,3.67 0,0 0,3.67 3.67h41a2.35,2.35 0,0 1,2.35 2.35L81.49,545.86L870.95,545.86L870.95,104.75ZM845.99,520.86L106.53,520.86L106.53,213.96a17.06,17.06 0,0 0,-17.06 -17.06h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.15a2.5,2.5 0,0 1,2.5 -2.5h784z"
|
||||
android:fillColor="#9f9f9e"/>
|
||||
<path
|
||||
android:pathData="M846,627.3L846,1018.4L106.5,1018.4L106.5,711.5a17,17 0,0 0,-7.2 -13.9v-70.3z"
|
||||
android:pathData="M845.99,129.75L845.99,520.86L106.53,520.86L106.53,213.96a17,17 0,0 0,-7.2 -13.92v-70.29z"
|
||||
android:fillColor="#cbcccb"/>
|
||||
<path
|
||||
android:pathData="m99.3,627.3v70.3a17,17 0,0 0,-9.9 -3.1h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.1a2.5,2.5 0,0 1,2.5 -2.5z"
|
||||
android:pathData="m99.33,129.75v70.29a17,17 0,0 0,-9.86 -3.14h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.15a2.5,2.5 0,0 1,2.5 -2.5z"
|
||||
android:fillColor="#b7b7b7"/>
|
||||
<path
|
||||
android:pathData="M25.4,750.9h13.5v148.4h-13.5z"
|
||||
android:pathData="M25.45,253.39h13.53v148.4h-13.53z"
|
||||
android:fillColor="#9f9f9e"/>
|
||||
<path
|
||||
android:pathData="M417.9,487.9L513.9,487.9A3.9,3.9 0,0 1,517.9 491.8L517.9,548.6A3.9,3.9 0,0 1,513.9 552.5L417.9,552.5A3.9,3.9 0,0 1,413.9 548.6L413.9,491.8A3.9,3.9 0,0 1,417.9 487.9z"
|
||||
android:pathData="m430.64,95.71h71.71a2.55,2.55 0,0 1,2.55 2.55v6.48h-76.8v-6.48a2.55,2.55 0,0 1,2.54 -2.55z"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="m430.6,593.2h71.7a2.5,2.5 0,0 1,2.5 2.5v6.5h-76.8v-6.5a2.5,2.5 0,0 1,2.5 -2.5z"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="m419.2,552.5h92.4v28.1a2.5,2.5 0,0 1,-2.5 2.5h-87.3a2.5,2.5 0,0 1,-2.5 -2.5v-28.1z"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="M433.3,583.2h66v10h-66z"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="M507.2,487.9l0,-4.3l-82.7,0l0,4.3"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="m465.9,1v0a44,44 0,0 1,44 44v438.6h-88v-438.5a44,44 0,0 1,44 -44z"
|
||||
android:fillColor="#383838"/>
|
||||
<path
|
||||
android:pathData="M421.9,65.7h88v6h-88z"
|
||||
android:fillColor="#2c2d2d"/>
|
||||
<path
|
||||
android:pathData="M421.9,92.9h88v6h-88z"
|
||||
android:fillColor="#2c2d2d"/>
|
||||
<path
|
||||
android:pathData="M846,627.3L846,1018.4L106.5,1018.4L106.5,711.5a17.1,17.1 0,0 0,-17.1 -17.1h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.1a2.5,2.5 0,0 1,2.5 -2.5h784m25,-25L34.5,602.3v113.5a3.7,3.7 0,0 0,3.7 3.7h41a2.3,2.3 0,0 1,2.3 2.3L81.5,1043.4L870.9,1043.4L870.9,602.3Z"
|
||||
android:pathData="m436.27,3.17h60.88a6.2,4.85 0,0 1,6.2 4.85v77.33h-73.28v-77.33a6.2,4.85 0,0 1,6.2 -4.85z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M99.3,697.5L99.3,627.3"
|
||||
android:pathData="M425.88,20.14L506.28,20.14A5.55,5.55 0,0 1,511.83 25.69L511.83,70.55A5.55,5.55 0,0 1,506.28 76.1L425.88,76.1A5.55,5.55 0,0 1,420.33 70.55L420.33,25.69A5.55,5.55 0,0 1,425.88 20.14z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M25.4,750.9h13.5v148.4h-13.5z"
|
||||
android:pathData="m511.8,24.48v47.25a5.52,4.31 0,0 1,-5.55 4.34h-80.37a5.55,4.34 0,0 1,-5.59 -4.34v-47.25a5.55,4.34 0,0 1,5.59 -4.34h80.51a5.52,4.31 0,0 1,5.41 4.34z"
|
||||
android:strokeWidth="3.16706"
|
||||
android:fillColor="#9f9f9e"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M433.29,85.68h65.99v10.03h-65.99z"
|
||||
android:fillColor="#b1a368"/>
|
||||
<path
|
||||
android:pathData="M845.99,129.75L845.99,520.86L106.53,520.86L106.53,213.96a17.06,17.06 0,0 0,-17.06 -17.06h-27.5a2.5,2.5 0,0 1,-2.5 -2.5v-62.15a2.5,2.5 0,0 1,2.5 -2.5h784m25,-25L34.47,104.75v113.48a3.68,3.68 0,0 0,3.67 3.67h41a2.35,2.35 0,0 1,2.35 2.35L81.49,545.86L870.95,545.86L870.95,104.75Z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m898.5,633h4.7a5.7,5.7 0,0 1,5.7 5.7v84.6a5.7,5.7 0,0 1,-5.7 5.7h-4.7"
|
||||
android:pathData="M99.34,200.04L99.34,129.75"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m465.9,1v0a44,44 0,0 1,44 44v438.6h-88v-438.5a44,44 0,0 1,44 -44z"
|
||||
android:pathData="M25.45,253.39h13.53v148.4h-13.53z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M417.9,487.9L513.9,487.9A3.9,3.9 0,0 1,517.9 491.8L517.9,548.6A3.9,3.9 0,0 1,513.9 552.5L417.9,552.5A3.9,3.9 0,0 1,413.9 548.6L413.9,491.8A3.9,3.9 0,0 1,417.9 487.9z"
|
||||
android:pathData="m898.52,135.44h4.69a5.67,5.67 0,0 1,5.67 5.67v84.65a5.67,5.67 0,0 1,-5.67 5.67h-4.69"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m430.64,95.71h71.71a2.55,2.55 0,0 1,2.55 2.55v6.48h-76.8v-6.48a2.55,2.55 0,0 1,2.54 -2.55z"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m430.6,593.2h71.7a2.5,2.5 0,0 1,2.5 2.5v6.5h-76.8v-6.5a2.5,2.5 0,0 1,2.5 -2.5z"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m419.2,552.5h92.4v28.1a2.5,2.5 0,0 1,-2.5 2.5h-87.3a2.5,2.5 0,0 1,-2.5 -2.5v-28.1z"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M433.3,583.2h66v10h-66z"
|
||||
android:pathData="M433.29,85.68h65.99v10.03h-65.99z"
|
||||
android:strokeWidth="1.99"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M507.2,487.9l0,-4.3l-82.7,0l0,4.3"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M421.9,65.7h88v6h-88z"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M421.9,92.9h88v6h-88z"
|
||||
android:strokeWidth="2.04"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m78.6,649.8a14,14 0,1 0,14 14,13.9 13.9,0 0,0 -14,-14zM78.6,671.3a7.6,7.6 0,1 1,7.5 -7.6,7.6 7.6,0 0,1 -7.5,7.6z"
|
||||
android:pathData="m78.62,152.33a14,14 0,1 0,14 14,13.95 13.95,0 0,0 -14,-14zM78.62,173.83a7.55,7.55 0,1 1,7.54 -7.55,7.55 7.55,0 0,1 -7.54,7.55z"
|
||||
android:fillColor="#9f9f9e"/>
|
||||
<path
|
||||
android:pathData="M78.6,663.8m-7.6,0a7.6,7.6 0,1 1,15.1 0a7.6,7.6 0,1 1,-15.1 0"
|
||||
android:pathData="M78.62,166.28m-7.55,0a7.55,7.55 0,1 1,15.1 0a7.55,7.55 0,1 1,-15.1 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M78.6,663.8m-13.9,0a13.9,13.9 0,1 1,27.9 0a13.9,13.9 0,1 1,-27.9 0"
|
||||
android:pathData="M78.62,166.28m-13.95,0a13.95,13.95 0,1 1,27.9 0a13.95,13.95 0,1 1,-27.9 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="M12.7,602.3L886.8,602.3A11.7,11.7 0,0 1,898.5 614L898.5,1031.7A11.7,11.7 0,0 1,886.8 1043.4L12.7,1043.4A11.7,11.7 0,0 1,1 1031.7L1,614A11.7,11.7 0,0 1,12.7 602.3z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m445.4,937.6c0,11.5 10.4,20.9 23.2,20.9 12.8,0 23.2,-9.3 23.2,-20.9 0,-11.5 -10.4,-20.9 -23.2,-20.9 -12.8,0 -23.2,9.3 -23.2,20.9z"
|
||||
android:pathData="m445.36,440.05c0,11.52 10.38,20.86 23.19,20.86 12.81,0 23.19,-9.34 23.19,-20.86 0,-11.52 -10.38,-20.86 -23.19,-20.86 -12.81,0 -23.19,9.34 -23.19,20.86z"
|
||||
android:strokeWidth="0.458227"
|
||||
android:fillColor="#4d4d4d"/>
|
||||
<path
|
||||
android:pathData="m469.4,1035.9c-119.8,0 -217.3,-93.4 -217.3,-208.2 0,-114.8 97.5,-208.2 217.3,-208.2 119.8,0 217.3,93.4 217.3,208.2 0,114.8 -97.5,208.2 -217.3,208.2zM469.4,649.3c-102.6,0 -186.1,80 -186.1,178.3 0,98.3 83.5,178.3 186.1,178.3 102.6,0 186.1,-80 186.1,-178.3 0,-98.3 -83.5,-178.3 -186.1,-178.3z"
|
||||
android:pathData="m469.4,538.4c-119.83,0 -217.32,-93.41 -217.32,-208.23 0,-114.82 97.48,-208.23 217.32,-208.23 119.83,0 217.32,93.41 217.32,208.23 0,114.82 -97.48,208.23 -217.32,208.23zM469.4,151.82c-102.64,0 -186.13,80.01 -186.13,178.35 0,98.33 83.5,178.35 186.13,178.35 102.62,0 186.13,-80.02 186.13,-178.35 0,-98.34 -83.51,-178.35 -186.13,-178.35z"
|
||||
android:strokeWidth="0.474832"
|
||||
android:fillColor="#4d4d4d"/>
|
||||
<path
|
||||
android:pathData="m468.6,889.5c-8.5,0 -15.5,-6.2 -15.5,-13.9v-23.5c0,-22.8 19.3,-40.1 36.4,-55.5 12.5,-11.3 25.5,-22.9 25.5,-32.2 0,-23.2 -20.8,-42 -46.4,-42 -26,0 -46.4,18 -46.4,41.1 0,7.7 -6.9,13.9 -15.5,13.9 -8.5,0 -15.5,-6.2 -15.5,-13.9 0,-38 34.7,-68.9 77.3,-68.9 42.6,0 77.3,31.3 77.3,69.8 0,20.8 -17.5,36.6 -34.5,51.8 -13.5,12.1 -27.3,24.6 -27.3,35.8v23.5c0,7.7 -6.9,13.9 -15.5,13.9z"
|
||||
android:pathData="m468.56,391.97c-8.54,0 -15.46,-6.23 -15.46,-13.91v-23.51c0,-22.75 19.33,-40.13 36.4,-55.47 12.51,-11.26 25.45,-22.89 25.45,-32.16 0,-23.18 -20.81,-42.04 -46.39,-42.04 -26.01,0 -46.39,18.05 -46.39,41.09 0,7.68 -6.93,13.91 -15.46,13.91 -8.54,0 -15.46,-6.23 -15.46,-13.91 0,-37.99 34.68,-68.9 77.31,-68.9 42.63,0 77.31,31.33 77.31,69.85 0,20.82 -17.55,36.59 -34.51,51.84 -13.45,12.07 -27.34,24.56 -27.34,35.78v23.51c0,7.68 -6.93,13.92 -15.46,13.92z"
|
||||
android:strokeWidth="0.458227"
|
||||
android:fillColor="#4d4d4d"/>
|
||||
android:fillColor="#4d4d4d"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M12.7,104.75L886.82,104.75A11.7,11.7 0,0 1,898.52 116.45L898.52,534.16A11.7,11.7 0,0 1,886.82 545.86L12.7,545.86A11.7,11.7 0,0 1,1 534.16L1,116.45A11.7,11.7 0,0 1,12.7 104.75z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#050606"/>
|
||||
<path
|
||||
android:pathData="m107.42,363.03 l-0.24,-156.31 -2.99,-3.72 -2.99,-3.72v-34.09,-34.09l150.65,0.05 150.65,0.05 -8.28,3.07c-19.32,7.16 -34.46,14.82 -50.22,25.41 -50.58,33.98 -84.36,88.87 -91.06,147.96 -1.43,12.63 -0.64,44.7 1.39,55.76 7.76,42.44 25.98,77.93 55.68,108.42 17.38,17.85 33.99,30.3 55.43,41.55l11.31,5.93 -134.54,0.02 -134.54,0.02z"
|
||||
android:strokeWidth="0.92"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0"/>
|
||||
<path
|
||||
android:pathData="m107.42,363.03 l-0.24,-156.31 -2.99,-3.72 -2.99,-3.72v-34.09,-34.09l150.65,0.05 150.65,0.05 -8.28,3.07c-19.32,7.16 -34.46,14.82 -50.22,25.41 -50.58,33.98 -84.36,88.87 -91.06,147.96 -1.43,12.63 -0.64,44.7 1.39,55.76 7.76,42.44 25.98,77.93 55.68,108.42 17.38,17.85 33.99,30.3 55.43,41.55l11.31,5.93 -134.54,0.02 -134.54,0.02z"
|
||||
android:strokeWidth="0.92"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0"/>
|
||||
<path
|
||||
android:pathData="m107.42,363.03 l-0.24,-156.31 -2.99,-3.72 -2.99,-3.72v-34.09,-34.09l150.65,0.05 150.65,0.05 -8.28,3.07c-19.32,7.16 -34.46,14.82 -50.22,25.41 -50.58,33.98 -84.36,88.87 -91.06,147.96 -1.43,12.63 -0.64,44.7 1.39,55.76 7.76,42.44 25.98,77.93 55.68,108.42 17.38,17.85 33.99,30.3 55.43,41.55l11.31,5.93 -134.54,0.02 -134.54,0.02z"
|
||||
android:strokeWidth="0.92"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M23,11.99l-2.44,-2.79l0.34,-3.69l-3.61,-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,11.99l2.44,2.79l-0.34,3.7l3.61,0.82L8.6,22.5l3.4,-1.47l3.4,1.46l1.89,-3.19l3.61,-0.82l-0.34,-3.69L23,11.99zM19.05,13.47l-0.56,0.65l0.08,0.85l0.18,1.95l-1.9,0.43l-0.84,0.19l-0.44,0.74l-0.99,1.68l-1.78,-0.77L12,18.85l-0.79,0.34l-1.78,0.77l-0.99,-1.67l-0.44,-0.74l-0.84,-0.19l-1.9,-0.43l0.18,-1.96l0.08,-0.85l-0.56,-0.65l-1.29,-1.47l1.29,-1.48l0.56,-0.65L5.43,9.01L5.25,7.07l1.9,-0.43l0.84,-0.19l0.44,-0.74l0.99,-1.68l1.78,0.77L12,5.14l0.79,-0.34l1.78,-0.77l0.99,1.68l0.44,0.74l0.84,0.19l1.9,0.43l-0.18,1.95l-0.08,0.85l0.56,0.65l1.29,1.47L19.05,13.47z"
|
||||
android:fillColor="#e3e3e3"/>
|
||||
</vector>
|
|
@ -628,4 +628,5 @@
|
|||
<string name="import_label">Import</string>
|
||||
<string name="request_metadata">Request Metadata</string>
|
||||
<string name="actions">Actions</string>
|
||||
<string name="firmware">Firmware</string>
|
||||
</resources>
|
||||
|
|
|
@ -33,11 +33,13 @@ material = "1.12.0"
|
|||
material3 = "1.3.2"
|
||||
mgrs = "2.1.3"
|
||||
navigation = "2.9.0"
|
||||
okhttp = "4.12.0"
|
||||
org-eclipse-paho-client-mqttv3 = "1.2.5"
|
||||
osmbonuspack = "6.9.0"
|
||||
osmdroid-android = "6.1.14"
|
||||
protobuf-gradle-plugin = "0.9.5"
|
||||
protobuf-kotlin = "4.31.0"
|
||||
retrofit = "2.11.0"
|
||||
room = "2.7.1"
|
||||
streamsupport-minifuture = "1.7.4"
|
||||
usb-serial-android = "3.9.0"
|
||||
|
@ -57,6 +59,8 @@ appintro = { group = "com.github.AppIntro", name = "AppIntro", version.ref = "ap
|
|||
awesome-app-rating = { group = "com.suddenh4x.ratingdialog", name = "awesome-app-rating", version.ref = "awesome-app-rating" }
|
||||
cardview = { group = "androidx.cardview", name = "cardview", version.ref = "cardview" }
|
||||
coil = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
|
||||
coil-network-core = { group = "io.coil-kt.coil3", name = "coil-network-core", version.ref = "coil" }
|
||||
coil-network-okhttp = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }
|
||||
coil-svg = { group = "io.coil-kt.coil3", name = "coil-svg", version.ref = "coil" }
|
||||
compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
|
||||
|
@ -106,6 +110,8 @@ material = { group = "com.google.android.material", name = "material", version.r
|
|||
mgrs = { group = "mil.nga", name = "mgrs", version.ref = "mgrs" }
|
||||
navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
|
||||
navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "navigation" }
|
||||
okhttp3 = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
||||
okhttp3-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
|
||||
org-eclipse-paho-client-mqttv3 = { group = "org.eclipse.paho", name = "org.eclipse.paho.client.mqttv3", version.ref = "org-eclipse-paho-client-mqttv3" }
|
||||
osmbonuspack = { group = "com.github.MKergall", name = "osmbonuspack", version.ref = "osmbonuspack" }
|
||||
osmdroid-android = { group = "org.osmdroid", name = "osmdroid-android", version.ref = "osmdroid-android" }
|
||||
|
@ -114,6 +120,8 @@ osmdroid-wms = { group = "org.osmdroid", name = "osmdroid-wms", version.ref = "o
|
|||
protobuf-gradle-plugin = { group = "com.google.protobuf", name = "protobuf-gradle-plugin", version.ref = "protobuf-gradle-plugin" }
|
||||
protobuf-kotlin = { group = "com.google.protobuf", name = "protobuf-kotlin", version.ref = "protobuf-kotlin" }
|
||||
protobuf-protoc = { group = "com.google.protobuf", name ="protoc", version.ref = "protobuf-kotlin" }
|
||||
retrofit2 = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
|
||||
retrofit2-kotlin-serialization = { group = "com.squareup.retrofit2", name = "converter-kotlinx-serialization", version.ref = "retrofit" }
|
||||
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
|
||||
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
|
||||
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
|
||||
|
@ -163,11 +171,14 @@ osm = ["osmdroid-android", "osmdroid-wms", "osmbonuspack", "mgrs"]
|
|||
# Firebase
|
||||
firebase = ["firebase-analytics", "firebase-crashlytics"]
|
||||
|
||||
#Protobuf
|
||||
# Protobuf
|
||||
protobuf = ["protobuf-kotlin"]
|
||||
|
||||
# retrofit
|
||||
retrofit = ["retrofit2", "retrofit2-kotlin-serialization", "okhttp3", "okhttp3-logging-interceptor"]
|
||||
|
||||
# coil
|
||||
coil = ["coil", "coil-svg"]
|
||||
coil = ["coil", "coil-network-core", "coil-network-okhttp", "coil-svg"]
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application" }
|
||||
|
@ -178,6 +189,7 @@ hilt = { id = "com.google.dagger.hilt.android" }
|
|||
kotlin-android = { id = "org.jetbrains.kotlin.android" }
|
||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize" }
|
||||
kotlin-serialization = { id = "kotlinx-serialization" }
|
||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization" }
|
||||
protobuf = { id = "com.google.protobuf" }
|
||||
android-library = { id = "com.android.library" }
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,46 @@
|
|||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.hilt)
|
||||
alias(libs.plugins.devtools.ksp)
|
||||
alias(libs.plugins.detekt)
|
||||
id("kotlinx-serialization")
|
||||
}
|
||||
|
||||
android {
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
compileSdk = 35
|
||||
defaultConfig {
|
||||
minSdk = 21
|
||||
}
|
||||
|
||||
namespace = "com.geeksville.mesh.network"
|
||||
compileOptions {
|
||||
sourceCompatibility(JavaVersion.VERSION_17)
|
||||
targetCompatibility(JavaVersion.VERSION_17)
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.hilt)
|
||||
implementation(libs.bundles.retrofit)
|
||||
implementation(libs.bundles.coil)
|
||||
ksp(libs.hilt.compiler)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
detektPlugins(libs.detekt.formatting)
|
||||
}
|
||||
|
||||
detekt {
|
||||
config.setFrom("../config/detekt/detekt.yml")
|
||||
baseline = file("../config/detekt/detekt-baseline.xml")
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeviceHardwareRemoteDataSource @Inject constructor(
|
||||
private val apiService: ApiService,
|
||||
) {
|
||||
suspend fun getAllDeviceHardware(): List<NetworkDeviceHardware> = withContext(Dispatchers.IO) {
|
||||
apiService.getDeviceHardware().body() ?: emptyList()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
class FirmwareReleaseRemoteDataSource @Inject constructor(
|
||||
private val apiService: ApiService,
|
||||
) {
|
||||
suspend fun getFirmwareReleases(): NetworkFirmwareReleases = withContext(Dispatchers.IO) {
|
||||
apiService.getFirmwareReleases().body() ?: NetworkFirmwareReleases()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.di
|
||||
|
||||
import android.content.Context
|
||||
import coil3.ImageLoader
|
||||
import coil3.disk.DiskCache
|
||||
import coil3.memory.MemoryCache
|
||||
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
|
||||
import coil3.request.crossfade
|
||||
import coil3.svg.SvgDecoder
|
||||
import coil3.util.DebugLogger
|
||||
import coil3.util.Logger
|
||||
import com.geeksville.mesh.network.BuildConfig
|
||||
import com.geeksville.mesh.network.retrofit.ApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val DISK_CACHE_PERCENT = 0.02
|
||||
private const val MEMORY_CACHE_PERCENT = 0.25
|
||||
@InstallIn(SingletonComponent::class)
|
||||
@Module
|
||||
class ApiModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOkHttpClient(): OkHttpClient {
|
||||
val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
if (BuildConfig.DEBUG) {
|
||||
setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
}
|
||||
}
|
||||
return OkHttpClient.Builder()
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideRetrofit(
|
||||
okHttpClient: OkHttpClient
|
||||
): Retrofit {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl("https://api.meshtastic.org/") // Replace with your base URL
|
||||
.addConverterFactory(
|
||||
Json.asConverterFactory(
|
||||
"application/json; charset=UTF8".toMediaType()
|
||||
)
|
||||
)
|
||||
.client(okHttpClient)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideApiService(retrofit: Retrofit): ApiService {
|
||||
return retrofit.create(ApiService::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun imageLoader(
|
||||
httpClient: OkHttpClient,
|
||||
@ApplicationContext application: Context,
|
||||
): ImageLoader {
|
||||
val sharedOkHttp = httpClient.newBuilder().build()
|
||||
return ImageLoader.Builder(application)
|
||||
.components {
|
||||
add(
|
||||
OkHttpNetworkFetcherFactory({ sharedOkHttp })
|
||||
)
|
||||
add(SvgDecoder.Factory())
|
||||
}
|
||||
.memoryCache {
|
||||
MemoryCache.Builder()
|
||||
.maxSizePercent(application, MEMORY_CACHE_PERCENT)
|
||||
.build()
|
||||
}
|
||||
.diskCache {
|
||||
DiskCache.Builder()
|
||||
.maxSizePercent(DISK_CACHE_PERCENT)
|
||||
.build()
|
||||
}
|
||||
.logger(if (BuildConfig.DEBUG) DebugLogger(Logger.Level.Verbose) else null)
|
||||
.crossfade(true)
|
||||
.build()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NetworkDeviceHardware(
|
||||
@SerialName("activelySupported")
|
||||
val activelySupported: Boolean = false,
|
||||
@SerialName("architecture")
|
||||
val architecture: String = "",
|
||||
@SerialName("displayName")
|
||||
val displayName: String = "",
|
||||
@SerialName("hasInkHud")
|
||||
val hasInkHud: Boolean? = null,
|
||||
@SerialName("hasMui")
|
||||
val hasMui: Boolean? = null,
|
||||
@SerialName("hwModel")
|
||||
val hwModel: Int = 0,
|
||||
@SerialName("hwModelSlug")
|
||||
val hwModelSlug: String = "",
|
||||
@SerialName("images")
|
||||
val images: List<String>? = null,
|
||||
@SerialName("partitionScheme")
|
||||
val partitionScheme: String? = null,
|
||||
@SerialName("platformioTarget")
|
||||
val platformioTarget: String = "",
|
||||
@SerialName("requiresDfu")
|
||||
val requiresDfu: Boolean? = null,
|
||||
@SerialName("supportLevel")
|
||||
val supportLevel: Int? = null,
|
||||
@SerialName("tags")
|
||||
val tags: List<String>? = null
|
||||
)
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NetworkFirmwareRelease(
|
||||
@SerialName("id")
|
||||
val id: String = "",
|
||||
@SerialName("page_url")
|
||||
val pageUrl: String = "",
|
||||
@SerialName("release_notes")
|
||||
val releaseNotes: String = "",
|
||||
@SerialName("title")
|
||||
val title: String = "",
|
||||
@SerialName("zip_url")
|
||||
val zipUrl: String = ""
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Releases(
|
||||
@SerialName("alpha")
|
||||
val alpha: List<NetworkFirmwareRelease> = listOf(),
|
||||
@SerialName("stable")
|
||||
val stable: List<NetworkFirmwareRelease> = listOf()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class NetworkFirmwareReleases(
|
||||
@SerialName("pullRequests")
|
||||
val pullRequests: List<NetworkFirmwareRelease> = listOf(),
|
||||
@SerialName("releases")
|
||||
val releases: Releases = Releases()
|
||||
)
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.network.retrofit
|
||||
|
||||
import com.geeksville.mesh.network.model.NetworkDeviceHardware
|
||||
import com.geeksville.mesh.network.model.NetworkFirmwareReleases
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface ApiService {
|
||||
@GET(".")
|
||||
suspend fun checkDeviceRegistration(@Query("deviceId") deviceId: String): Response<Unit>
|
||||
|
||||
@GET("resource/deviceHardware")
|
||||
suspend fun getDeviceHardware(): Response<List<NetworkDeviceHardware>>
|
||||
|
||||
@GET("/github/firmware/list")
|
||||
suspend fun getFirmwareReleases(): Response<NetworkFirmwareReleases>
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
include ':app'
|
||||
rootProject.name='Meshtastic Android'
|
||||
include ':network'
|
||||
|
|