Skip to content
Merged
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
157 changes: 157 additions & 0 deletions Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,159 @@
}
}
},
"Last: Repeat decreased to %@ · %@" : {
"comment" : "Reading mode status line for the last repeat counter decrease. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Wiederholung auf %1$@ verringert · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Repeat decreased to %1$@ · %2$@"
}
}
}
},
"Last: Repeat increased to %@ · %@" : {
"comment" : "Reading mode status line for the last repeat counter increase. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Wiederholung auf %1$@ erhöht · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Repeat increased to %1$@ · %2$@"
}
}
}
},
"Last: Repeat set to %@ · %@" : {
"comment" : "Reading mode status line for a directly set repeat counter. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Wiederholung auf %1$@ gesetzt · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Repeat set to %1$@ · %2$@"
}
}
}
},
"Last: Row decreased to %@ · %@" : {
"comment" : "Reading mode status line for the last row counter decrease. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Reihe auf %1$@ verringert · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Row decreased to %1$@ · %2$@"
}
}
}
},
"Last: Row increased to %@ · %@" : {
"comment" : "Reading mode status line for the last row counter increase. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Reihe auf %1$@ erhöht · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Row increased to %1$@ · %2$@"
}
}
}
},
"Last: Row set to %@ · %@" : {
"comment" : "Reading mode status line for a directly set row counter. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Reihe auf %1$@ gesetzt · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Row set to %1$@ · %2$@"
}
}
}
},
"Last: Stitches decreased to %@ · %@" : {
"comment" : "Reading mode status line for the last stitch counter decrease. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Maschen auf %1$@ verringert · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Stitches decreased to %1$@ · %2$@"
}
}
}
},
"Last: Stitches increased to %@ · %@" : {
"comment" : "Reading mode status line for the last stitch counter increase. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Maschen auf %1$@ erhöht · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Stitches increased to %1$@ · %2$@"
}
}
}
},
"Last: Stitches set to %@ · %@" : {
"comment" : "Reading mode status line for a directly set stitch counter. The first placeholder is the new value and the second is the local time or date and time.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "machine_translated",
"value" : "Zuletzt: Maschen auf %1$@ gesetzt · %2$@"
}
},
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Last: Stitches set to %1$@ · %2$@"
}
}
}
},
"LoopLine" : {
"comment" : "The name of the app.",
"isCommentAutoGenerated" : true,
Expand Down Expand Up @@ -846,6 +999,7 @@
},
"of %lld" : {
"comment" : "Text appended to the end of a counter value to indicate the total number of rows. The argument is the current row number, the second is the total number of rows.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"de" : {
Expand Down Expand Up @@ -1198,6 +1352,7 @@
},
"REPEAT" : {
"comment" : "Label for the number of repeats.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"de" : {
Expand Down Expand Up @@ -1290,6 +1445,7 @@
},
"ROW" : {
"comment" : "Label for the number of the current row.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"de" : {
Expand Down Expand Up @@ -1515,6 +1671,7 @@
},
"STITCHES" : {
"comment" : "Label for the number of stitches counter in the reading controls.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true,
"localizations" : {
"de" : {
Expand Down
4 changes: 2 additions & 2 deletions LoopLine.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = ZRUVWXD37Y;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
Expand Down Expand Up @@ -450,7 +450,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = ZRUVWXD37Y;
ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
Expand Down
7 changes: 7 additions & 0 deletions LoopLine/Models/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ final class Project {
var repeatCurrent: Int
var currentStitch: Int = 0
var repeatTotal: Int?
var selectedTrackingMetricRawValue: String = ReadingTrackingMetric.row.rawValue
var lastCounterMetricRawValue: String?
var lastCounterValue: Int?
var lastCounterChangeDirectionRawValue: String?
var lastCounterChangedAt: Date?
var lastPDFPageIndex: Int = 0
var lastPDFPageVerticalPosition: Double = 0
var rows: [String]
var sourceText: String?
var sourceFilePath: String?
Expand Down
98 changes: 98 additions & 0 deletions LoopLine/Models/ReadingTrackingMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,101 @@ enum ReadingTrackingMetric: String, CaseIterable, Identifiable {
}
}
}

enum CounterChangeDirection: String {
case increased
case decreased
case set
}

struct LastCounterChange: Equatable {
let metric: ReadingTrackingMetric
let value: Int
let direction: CounterChangeDirection
let timestamp: Date
}

extension Project {
var lastCounterChange: LastCounterChange? {
guard let metricRawValue = lastCounterMetricRawValue,
let metric = ReadingTrackingMetric(rawValue: metricRawValue),
let value = lastCounterValue,
let directionRawValue = lastCounterChangeDirectionRawValue,
let direction = CounterChangeDirection(rawValue: directionRawValue),
let timestamp = lastCounterChangedAt else {
return nil
}

return LastCounterChange(
metric: metric,
value: value,
direction: direction,
timestamp: timestamp
)
}

func recordLastCounterChange(
metric: ReadingTrackingMetric,
value: Int,
direction: CounterChangeDirection,
timestamp: Date = .now
) {
lastCounterMetricRawValue = metric.rawValue
lastCounterValue = value
lastCounterChangeDirectionRawValue = direction.rawValue
lastCounterChangedAt = timestamp
}

func clearLastCounterChange() {
lastCounterMetricRawValue = nil
lastCounterValue = nil
lastCounterChangeDirectionRawValue = nil
lastCounterChangedAt = nil
}
}

enum LastCounterChangeFormatter {
static func timestampText(
for date: Date,
now: Date = .now,
calendar: Calendar = .autoupdatingCurrent,
locale: Locale = .autoupdatingCurrent
) -> String {
if calendar.isDate(date, inSameDayAs: now) {
return date.formatted(.dateTime.hour().minute().locale(locale))
}

return date.formatted(.dateTime.year().month(.abbreviated).day().hour().minute().locale(locale))
}

static func statusText(
for change: LastCounterChange,
now: Date = .now,
calendar: Calendar = .autoupdatingCurrent,
locale: Locale = .autoupdatingCurrent
) -> String {
let value = change.value.formatted(.number.locale(locale))
let timestamp = timestampText(for: change.timestamp, now: now, calendar: calendar, locale: locale)

switch (change.metric, change.direction) {
case (.row, .increased):
return String(localized: "Last: Row increased to \(value) · \(timestamp)", comment: "Reading mode status line for the last row counter increase. The first placeholder is the new value and the second is the local time or date and time.")
case (.row, .decreased):
return String(localized: "Last: Row decreased to \(value) · \(timestamp)", comment: "Reading mode status line for the last row counter decrease. The first placeholder is the new value and the second is the local time or date and time.")
case (.row, .set):
return String(localized: "Last: Row set to \(value) · \(timestamp)", comment: "Reading mode status line for a directly set row counter. The first placeholder is the new value and the second is the local time or date and time.")
case (.stitches, .increased):
return String(localized: "Last: Stitches increased to \(value) · \(timestamp)", comment: "Reading mode status line for the last stitch counter increase. The first placeholder is the new value and the second is the local time or date and time.")
case (.stitches, .decreased):
return String(localized: "Last: Stitches decreased to \(value) · \(timestamp)", comment: "Reading mode status line for the last stitch counter decrease. The first placeholder is the new value and the second is the local time or date and time.")
case (.stitches, .set):
return String(localized: "Last: Stitches set to \(value) · \(timestamp)", comment: "Reading mode status line for a directly set stitch counter. The first placeholder is the new value and the second is the local time or date and time.")
case (.repeatCount, .increased):
return String(localized: "Last: Repeat increased to \(value) · \(timestamp)", comment: "Reading mode status line for the last repeat counter increase. The first placeholder is the new value and the second is the local time or date and time.")
case (.repeatCount, .decreased):
return String(localized: "Last: Repeat decreased to \(value) · \(timestamp)", comment: "Reading mode status line for the last repeat counter decrease. The first placeholder is the new value and the second is the local time or date and time.")
case (.repeatCount, .set):
return String(localized: "Last: Repeat set to \(value) · \(timestamp)", comment: "Reading mode status line for a directly set repeat counter. The first placeholder is the new value and the second is the local time or date and time.")
}
}
}
Loading
Loading