Skip to content

Commit

Permalink
iOS TodoList
Browse files Browse the repository at this point in the history
  • Loading branch information
Almaju committed Jan 31, 2024
1 parent 8a76e8f commit b7c65e7
Show file tree
Hide file tree
Showing 16 changed files with 515 additions and 105 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Rust
/target

# IDE
.vscode
1 change: 0 additions & 1 deletion Cargo.lock

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

1 change: 0 additions & 1 deletion application/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ edition = "2021"
domain = { path = "../domain" }
framework = { path = "../crates/framework" }
serde = { version = "1.0", features = ["derive"] }
uniffi = { version = "0.25.3" }
4 changes: 2 additions & 2 deletions application/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use serde::Deserialize;
#[derive(Deserialize)]
pub enum Command {
AddTask { name: String },
RemoveTask { index: u32 },
CompleteTask { index: u32 },
RemoveTask { index: usize },
CompleteTask { index: usize },
}

#[derive(Debug, Error)]
Expand Down
2 changes: 0 additions & 2 deletions application/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@ pub mod port;
pub mod projection;
pub mod query;
pub mod snapshot;

uniffi::setup_scaffolding!();
8 changes: 4 additions & 4 deletions application/src/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ use domain::todolist_event::TodoListEvent;
use framework::*;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, Debug, Serialize, Deserialize, uniffi::Record)]
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct TodoList {
pub tasks: Vec<Task>,
}

#[derive(Clone, Debug, Serialize, Deserialize, uniffi::Record)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Task {
pub index: u32,
pub index: usize,
pub name: String,
pub status: TaskStatus,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, uniffi::Enum)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum TaskStatus {
Created,
Completed,
Expand Down
1 change: 1 addition & 0 deletions application/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{port::TodoListRepository, projection::TodoList};
use framework::*;
use serde::Deserialize;

#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[derive(Deserialize)]
pub struct GetTodoListQuery {}

Expand Down
11 changes: 6 additions & 5 deletions clients/mobile/build-ios.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ cargo run --bin uniffi-bindgen generate --library ../../target/debug/libmobile.d

# Add the ios targets and build
for TARGET in \
aarch64-apple-ios \
aarch64-apple-ios-sim
aarch64-apple-ios \
aarch64-apple-ios-sim
do
rustup target add $TARGET
# Apple's App Sandbox disallows SysV semaphores; use POSIX semaphores instead
Expand All @@ -19,16 +19,17 @@ done
# Rename *.modulemap to module.modulemap
mv ./bindings/mobileFFI.modulemap ./bindings/module.modulemap


# Move the Swift file to the project
rm ./ios/TodoList/Mobile.swift
mv ./bindings/mobile.swift ./ios/TodoList/Mobile.swift

# # Recreate XCFramework
rm -rf "ios/Mobile.xcframework"
xcodebuild -create-xcframework \
-library ../../target/aarch64-apple-ios-sim/release/libmobile.a -headers ./bindings \
-library ../../target/aarch64-apple-ios/release/libmobile.a -headers ./bindings \
-output "ios/Mobile.xcframework"
-library ../../target/aarch64-apple-ios-sim/release/libmobile.a -headers ./bindings \
-library ../../target/aarch64-apple-ios/release/libmobile.a -headers ./bindings \
-output "ios/Mobile.xcframework"

# # Cleanup
rm -rf bindings
8 changes: 4 additions & 4 deletions clients/mobile/ios/TodoList.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
objects = {

/* Begin PBXBuildFile section */
0CB5ABC72B6A507100E96E34 /* Mobile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB5ABC62B6A507100E96E34 /* Mobile.swift */; };
0CE410A42B59CAE400FD01AF /* TodoListApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE410A32B59CAE400FD01AF /* TodoListApp.swift */; };
0CE410A62B59CAE400FD01AF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE410A52B59CAE400FD01AF /* ContentView.swift */; };
0CE410A82B59CAE500FD01AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0CE410A72B59CAE500FD01AF /* Assets.xcassets */; };
0CE410AB2B59CAE600FD01AF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0CE410AA2B59CAE600FD01AF /* Preview Assets.xcassets */; };
0CE410B32B59CB1D00FD01AF /* Mobile.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE410B12B59CB0B00FD01AF /* Mobile.xcframework */; };
0CE410B42B59CB1D00FD01AF /* Mobile.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0CE410B12B59CB0B00FD01AF /* Mobile.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0CE410B72B59CDB600FD01AF /* Mobile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CE410B62B59CDB600FD01AF /* Mobile.swift */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -31,13 +31,13 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
0CB5ABC62B6A507100E96E34 /* Mobile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mobile.swift; sourceTree = "<group>"; };
0CE410A02B59CAE400FD01AF /* TodoList.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TodoList.app; sourceTree = BUILT_PRODUCTS_DIR; };
0CE410A32B59CAE400FD01AF /* TodoListApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListApp.swift; sourceTree = "<group>"; };
0CE410A52B59CAE400FD01AF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
0CE410A72B59CAE500FD01AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0CE410AA2B59CAE600FD01AF /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
0CE410B12B59CB0B00FD01AF /* Mobile.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Mobile.xcframework; sourceTree = SOURCE_ROOT; };
0CE410B62B59CDB600FD01AF /* Mobile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mobile.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -71,9 +71,9 @@
0CE410A22B59CAE400FD01AF /* TodoList */ = {
isa = PBXGroup;
children = (
0CB5ABC62B6A507100E96E34 /* Mobile.swift */,
0CE410B12B59CB0B00FD01AF /* Mobile.xcframework */,
0CE410A32B59CAE400FD01AF /* TodoListApp.swift */,
0CE410B62B59CDB600FD01AF /* Mobile.swift */,
0CE410A52B59CAE400FD01AF /* ContentView.swift */,
0CE410A72B59CAE500FD01AF /* Assets.xcassets */,
0CE410A92B59CAE600FD01AF /* Preview Content */,
Expand Down Expand Up @@ -160,7 +160,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0CE410B72B59CDB600FD01AF /* Mobile.swift in Sources */,
0CB5ABC72B6A507100E96E34 /* Mobile.swift in Sources */,
0CE410A62B59CAE400FD01AF /* ContentView.swift in Sources */,
0CE410A42B59CAE400FD01AF /* TodoListApp.swift in Sources */,
);
Expand Down
Binary file not shown.
103 changes: 67 additions & 36 deletions clients/mobile/ios/TodoList/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,89 @@
import SwiftUI

struct ContentView: View {
@State private var todolist: String = "Loading..."
@State private var errorMessage: String = ""
@State private var newTaskName: String = ""
@State private var showError: Bool = false
@State private var todolist: TodoListDto?

var client = Client()

var body: some View {
NavigationView {
VStack {
List(tasks) { task in
Text(task.name)
}
NavigationView {
VStack {
List {
ForEach(todolist?.tasks ?? [], id: \.index) { task in
HStack {
Text(task.name)

HStack {
TextField("Enter task name", text: $newTaskName)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Spacer()

Button(action: addTask) {
Text("Send")
}
.padding()
Toggle(
"",
isOn: Binding(
get: { task.status == .completed },
set: { _, _ in
Task {
do {
try await client.completeTask(index: task.index)
todolist = try await client.getTodoList()
} catch {
handleError(error)
}
}
.navigationBarTitle("TodoList")
}
})
)
.labelsHidden()
}
}
}

HStack {
TextField("Enter task name", text: $newTaskName)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()

Button(
action: {
Task {
do {
try await client.addTask(name: newTaskName)
todolist = try await client.getTodoList()
newTaskName = ""
} catch {
handleError(error)
}
}

VStack {
Text(todolist)
Button("Add Task") {
Task {
await addTask()
},
label: {
Text("Add")
}
)
.padding()
}
}

}
.padding()
.onAppear {
loadTodoList()
.navigationBarTitle("TodoList")
.alert(isPresented: $showError) {
Alert(
title: Text("Error"), message: Text(errorMessage), dismissButton: .default(Text("OK")))
}
}
}

private func loadTodoList() {
Task {
todolist = await client.getTodolist()
private func handleError(_ error: Error) {
if let errorDto = error as? ErrorDto {
switch errorDto {
case .Error(let message):
errorMessage = message
}
showError = true
} else {
// Handle other errors
errorMessage = error.localizedDescription
showError = true
}
}

private func addTask() async {
await client.addTask(name: "Hello iOS")
let res = await client.getTodolist()
todolist = res
}

}

#Preview {
Expand Down
Loading

0 comments on commit b7c65e7

Please sign in to comment.