Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions MeshChatMVP.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
A100000A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A200000A /* Assets.xcassets */; };
A100000B /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A200000C /* ChatView.swift */; };
A100000C /* DebugDashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A200000D /* DebugDashboardView.swift */; };
A100000D /* Contact.swift in Sources */ = {isa = PBXBuildFile; fileRef = A200000E /* Contact.swift */; };
A100000E /* PersistedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A200000F /* PersistedMessage.swift */; };
A100000F /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000010 /* Alert.swift */; };
A1000010 /* Vouch.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000011 /* Vouch.swift */; };
A1000011 /* NodeSighting.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000012 /* NodeSighting.swift */; };
A1000012 /* AlertPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000013 /* AlertPayload.swift */; };
A1000013 /* VouchPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000014 /* VouchPayload.swift */; };
A1000014 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000015 /* DatabaseManager.swift */; };
A1000015 /* MapTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000016 /* MapTabView.swift */; };
A1000016 /* MapLabelModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000017 /* MapLabelModels.swift */; };
D974FBAF2F651AD7008F4874 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = D974FBAE2F651AD7008F4874 /* GRDB */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -35,13 +46,24 @@
A200000A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A200000C /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; };
A200000D /* DebugDashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugDashboardView.swift; sourceTree = "<group>"; };
A200000E /* Contact.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contact.swift; sourceTree = "<group>"; };
A200000F /* PersistedMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistedMessage.swift; sourceTree = "<group>"; };
A2000010 /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = "<group>"; };
A2000011 /* Vouch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vouch.swift; sourceTree = "<group>"; };
A2000012 /* NodeSighting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeSighting.swift; sourceTree = "<group>"; };
A2000013 /* AlertPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertPayload.swift; sourceTree = "<group>"; };
A2000014 /* VouchPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VouchPayload.swift; sourceTree = "<group>"; };
A2000015 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
A2000016 /* MapTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTabView.swift; sourceTree = "<group>"; };
A2000017 /* MapLabelModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLabelModels.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
A3000001 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D974FBAF2F651AD7008F4874 /* GRDB in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -63,13 +85,23 @@
A2000002 /* ContentView.swift */,
A200000C /* ChatView.swift */,
A200000D /* DebugDashboardView.swift */,
A2000016 /* MapTabView.swift */,
A2000003 /* BluetoothMeshService.swift */,
A2000004 /* MeshEnvelope.swift */,
A2000005 /* MessageType.swift */,
A2000006 /* DeviceIdentity.swift */,
A2000007 /* ChatPayload.swift */,
A2000008 /* AnnouncementPayload.swift */,
A2000009 /* ChatMessage.swift */,
A200000E /* Contact.swift */,
A200000F /* PersistedMessage.swift */,
A2000010 /* Alert.swift */,
A2000011 /* Vouch.swift */,
A2000012 /* NodeSighting.swift */,
A2000013 /* AlertPayload.swift */,
A2000014 /* VouchPayload.swift */,
A2000015 /* DatabaseManager.swift */,
A2000017 /* MapLabelModels.swift */,
A200000A /* Assets.xcassets */,
);
path = MeshChatMVP;
Expand Down Expand Up @@ -127,6 +159,9 @@
Base,
);
mainGroup = A4000000;
packageReferences = (
D974FBAD2F651AD7008F4874 /* XCRemoteSwiftPackageReference "GRDB" */,
);
productRefGroup = A4000002 /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down Expand Up @@ -163,6 +198,16 @@
A1000007 /* ChatPayload.swift in Sources */,
A1000008 /* AnnouncementPayload.swift in Sources */,
A1000009 /* ChatMessage.swift in Sources */,
A100000D /* Contact.swift in Sources */,
A100000E /* PersistedMessage.swift in Sources */,
A100000F /* Alert.swift in Sources */,
A1000010 /* Vouch.swift in Sources */,
A1000011 /* NodeSighting.swift in Sources */,
A1000012 /* AlertPayload.swift in Sources */,
A1000013 /* VouchPayload.swift in Sources */,
A1000014 /* DatabaseManager.swift in Sources */,
A1000015 /* MapTabView.swift in Sources */,
A1000016 /* MapLabelModels.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -218,7 +263,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 6VX7H735DM;
DEVELOPMENT_TEAM = U4P4H7KRKC;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = MeshChat;
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "MeshChat uses Bluetooth LE to discover nearby devices and relay messages.";
Expand All @@ -245,7 +290,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 6VX7H735DM;
DEVELOPMENT_TEAM = U4P4H7KRKC;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = MeshChat;
INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "MeshChat uses Bluetooth LE to discover nearby devices and relay messages.";
Expand Down Expand Up @@ -288,6 +333,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
D974FBAD2F651AD7008F4874 /* XCRemoteSwiftPackageReference "GRDB" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/groue/GRDB.swift";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.0.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
D974FBAE2F651AD7008F4874 /* GRDB */ = {
isa = XCSwiftPackageProductDependency;
package = D974FBAD2F651AD7008F4874 /* XCRemoteSwiftPackageReference "GRDB" */;
productName = GRDB;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = A6000001 /* Project object */;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions MeshChatMVP/Alert.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Foundation
import GRDB

struct Alert: Codable, FetchableRecord, PersistableRecord, Identifiable {
static let databaseTableName = "alerts"

var id: String
var authorID: String // FK → contacts.id
var type: AlertType
var severity: Int // 1 = low, 2 = medium, 3 = high
var lat: Double
var lon: Double
var description: String
var createdAt: Int64 // unix timestamp (seconds)
var expiresAt: Int64 // unix timestamp (seconds)
var trustScore: Double // 0.0–1.0, computed and cached

enum AlertType: String, Codable {
case hazard // negative — danger, threat
case aid // positive — help, resources
case other // neutral — info
}

var isExpired: Bool {
Int64(Date().timeIntervalSince1970) > expiresAt
}

/// Default expiry offset in seconds based on alert type.
static func defaultExpiresAt(for type: AlertType) -> Int64 {
let offset: Int64
switch type {
case .hazard: offset = 6 * 3600 // 6 hours
case .aid: offset = 24 * 3600 // 24 hours
case .other: offset = 12 * 3600 // 12 hours
}
return Int64(Date().timeIntervalSince1970) + offset
}
}
13 changes: 13 additions & 0 deletions MeshChatMVP/AlertPayload.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

/// Wire payload for a `.alert` envelope.
struct AlertPayload: Codable {
var alertID: String
var type: Alert.AlertType
var severity: Int
var lat: Double
var lon: Double
var description: String
var createdAt: Int64 // unix timestamp (seconds)
var expiresAt: Int64 // unix timestamp (seconds)
}
Loading