Skip to content

Commit

Permalink
Added demo project.
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-salari authored Dec 29, 2024
0 parents commit 81da255
Show file tree
Hide file tree
Showing 32 changed files with 2,350 additions and 0 deletions.
483 changes: 483 additions & 0 deletions Characters.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"originHash" : "61aeeb9f538ff55edd0f4b73c2ba0b49dcf9afc9b86ee53bacf1c32562250bda",
"pins" : [
{
"identity" : "fakery",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vadymmarkov/Fakery",
"state" : {
"revision" : "71cb3bf36a808534659d1248780c2bf3c4c4fc91",
"version" : "5.1.0"
}
}
],
"version" : 3
}
102 changes: 102 additions & 0 deletions Characters.xcodeproj/xcshareddata/xcschemes/Characters.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2970E6F2CFDE11B004CEBDA"
BuildableName = "Characters.app"
BlueprintName = "Characters"
ReferencedContainer = "container:Characters.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2970E7F2CFDE11D004CEBDA"
BuildableName = "CharactersTests.xctest"
BlueprintName = "CharactersTests"
ReferencedContainer = "container:Characters.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2970E892CFDE11D004CEBDA"
BuildableName = "CharactersUITests.xctest"
BlueprintName = "CharactersUITests"
ReferencedContainer = "container:Characters.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2970E6F2CFDE11B004CEBDA"
BuildableName = "Characters.app"
BlueprintName = "Characters"
ReferencedContainer = "container:Characters.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E2970E6F2CFDE11B004CEBDA"
BuildableName = "Characters.app"
BlueprintName = "Characters"
ReferencedContainer = "container:Characters.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
11 changes: 11 additions & 0 deletions Characters/Assets.xcassets/AccentColor.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
35 changes: 35 additions & 0 deletions Characters/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions Characters/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
20 changes: 20 additions & 0 deletions Characters/Assets.xcassets/alive.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xFC",
"green" : "0xF6",
"red" : "0xE8"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
20 changes: 20 additions & 0 deletions Characters/Assets.xcassets/dead.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xEB",
"green" : "0xE6",
"red" : "0xFF"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
23 changes: 23 additions & 0 deletions Characters/CharactersApp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Rick_And_MortyApp.swift
// Characters App
//
// Created by Piotr Salari on 10/11/2024.
//

import SwiftUI

/// The main entry point of the Rick and Morty app.
/// This struct is responsible for setting up the main window and launching the app.
@main
struct Rick_And_MortyApp: App {
// MARK: - Body

var body: some Scene {
/// The main window group of the app.
WindowGroup {
// The root view of the app is ContentView
ContentView()
}
}
}
51 changes: 51 additions & 0 deletions Characters/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// ContentView.swift
// Characters App
//
// Created by Piotr Salari on 10/11/2024.
//

import SwiftUI

/// The main view of the app which displays a list of characters.
/// It handles the navigation to a detailed view of the selected character.
struct ContentView: View {
// MARK: - Constants

/// Struct to store reusable constants.
private struct Constants {
/// The initial navigation path (empty by default).
static let initialPath = NavigationPath()
}

// MARK: - Properties

/// The character service used to fetch character data.
var characterService: CharacterServiceInterface = CharacterService()

/// The navigation path to manage the navigation stack.
@State
private var path = NavigationPath()

// MARK: - Body

var body: some View {
NavigationStack(path: $path) {
// CharacterListView displays a list of characters
CharacterListView { character in
// When a character is selected, navigate to the character details view
path.append(character)
}
.navigationDestination(for: Character.self) { character in
// CharacterDetailsView shows detailed information about the selected character
CharacterDetailsView(
viewModel: CharacterDetailsViewModel(character)
)
}
}
}
}

#Preview {
ContentView(characterService: CharacterServiceDouble())
}
68 changes: 68 additions & 0 deletions Characters/Network/APIs/CharacterQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// CharacterQuery.swift
// Characters App
//
// Created by Piotr Salari on 10/11/2024.
//

import Foundation

// MARK: - CharacterQuery

/// A struct representing a query for fetching character data.
/// - `page`: The page number for paginated results.
/// - `status`: The status of the character, such as "alive", "dead", or "unknown".
struct CharacterQuery: Hashable {
/// The page number for paginated results.
/// - Example: 1, 2, 3, etc.
let page: Int

/// The status of the character, optional.
/// - Possible values: `.alive`, `.dead`, `.unknown`, or `nil`.
let status: CharacterStatus?
}

// MARK: - CharacterQuery Query items

extension CharacterQuery {
/// Converts the `CharacterQuery` instance to an array of `URLQueryItem`s.
///
/// This function uses reflection to inspect all properties of the `CharacterQuery` struct
/// and converts them into key-value pairs suitable for URL query parameters.
///
/// - Returns: An array of `URLQueryItem`s representing the properties of the struct.
func queryItems() -> [URLQueryItem] {
// Create a Mirror instance to reflect on the properties of `CharacterQuery`.
let mirror = Mirror(reflecting: self)

// Initialize an empty array to store the query items.
var queryItems: [URLQueryItem] = []

// Iterate over each property of the struct using the mirror.
for child in mirror.children {
// Check if the child has a label (the name of the property).
if let label = child.label {
// Handle the value of the property.
switch child.value {
case Optional<Any>.none:
// Skip properties with a `nil` value.
continue

case Optional<Any>.some(let x):
// Append a query item with the label (property name) and its string representation.
queryItems.append(URLQueryItem(
name: label,
value: String(describing: x)
))

default:
// Continue for any other cases (e.g., non-optional values).
continue
}
}
}

// Return the array of query items.
return queryItems
}
}
Loading

0 comments on commit 81da255

Please sign in to comment.