diff --git a/JShift.xcodeproj/project.pbxproj b/JShift.xcodeproj/project.pbxproj
index bf160e4..9193b17 100644
--- a/JShift.xcodeproj/project.pbxproj
+++ b/JShift.xcodeproj/project.pbxproj
@@ -234,7 +234,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1600;
- LastUpgradeCheck = 1600;
+ LastUpgradeCheck = 2600;
TargetAttributes = {
5436B6092CE8DEEC00E8CBFA = {
CreatedOnToolsVersion = 16.0;
@@ -375,9 +375,10 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"JShift/Preview Content\"";
- DEVELOPMENT_TEAM = 8KH9QD5V23;
+ ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = JShift/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
@@ -391,7 +392,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.6;
+ MARKETING_VERSION = 1.1.7;
PRODUCT_BUNDLE_IDENTIFIER = com.ShinKawakami.JShift.JShift;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -409,9 +410,10 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"JShift/Preview Content\"";
- DEVELOPMENT_TEAM = 8KH9QD5V23;
+ ENABLE_APP_SANDBOX = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
+ ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = JShift/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
@@ -425,7 +427,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.6;
+ MARKETING_VERSION = 1.1.7;
PRODUCT_BUNDLE_IDENTIFIER = com.ShinKawakami.JShift.JShift;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -469,6 +471,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = 8KH9QD5V23;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -493,6 +496,7 @@
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
@@ -533,6 +537,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = 8KH9QD5V23;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
@@ -550,6 +555,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
@@ -561,7 +567,6 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 8KH9QD5V23;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MARKETING_VERSION = 1.0;
@@ -580,7 +585,6 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 8KH9QD5V23;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MARKETING_VERSION = 1.0;
@@ -598,7 +602,6 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 8KH9QD5V23;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ShinKawakami.JShift.JShiftUITests;
@@ -615,7 +618,6 @@
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 8KH9QD5V23;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ShinKawakami.JShift.JShiftUITests;
diff --git a/JShift.xcodeproj/project.xcworkspace/xcuserdata/shin.xcuserdatad/UserInterfaceState.xcuserstate b/JShift.xcodeproj/project.xcworkspace/xcuserdata/shin.xcuserdatad/UserInterfaceState.xcuserstate
index 4be52c3..0cac6a4 100644
Binary files a/JShift.xcodeproj/project.xcworkspace/xcuserdata/shin.xcuserdatad/UserInterfaceState.xcuserstate and b/JShift.xcodeproj/project.xcworkspace/xcuserdata/shin.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/JShift/JShift.entitlements b/JShift/JShift.entitlements
index 87ac9f4..001264d 100644
--- a/JShift/JShift.entitlements
+++ b/JShift/JShift.entitlements
@@ -12,9 +12,5 @@
CloudKit
- com.apple.security.app-sandbox
-
- com.apple.security.files.user-selected.read-only
-
diff --git a/JShift/Models/CalendarManager.swift b/JShift/Models/CalendarManager.swift
index 4296e0a..3ba180b 100644
--- a/JShift/Models/CalendarManager.swift
+++ b/JShift/Models/CalendarManager.swift
@@ -23,6 +23,7 @@ final class CalendarManager {
private func syncCalendarList() async {
let fetchCalendarsQuery = GTLRCalendarQuery_CalendarListList.query()
+ fetchCalendarsQuery.maxResults = 250
await withCheckedContinuation { continuation in
service.executeQuery(fetchCalendarsQuery) { ticket, response, error in
if let error {
@@ -43,6 +44,7 @@ final class CalendarManager {
let fetchEventsQuery = GTLRCalendarQuery_EventsList.query(withCalendarId: calendarId)
fetchEventsQuery.singleEvents = true
fetchEventsQuery.syncToken = syncToken
+ fetchEventsQuery.maxResults = 1500
await withCheckedContinuation { continuation in
service.executeQuery(fetchEventsQuery) { ticket, response, error in
diff --git a/JShift/Models/SwiftData/JobSchemaV1.swift b/JShift/Models/SwiftData/JobSchemaV1.swift
index dd4cf3d..e3c5ce2 100644
--- a/JShift/Models/SwiftData/JobSchemaV1.swift
+++ b/JShift/Models/SwiftData/JobSchemaV1.swift
@@ -9,7 +9,7 @@ enum JobSchemaV1: VersionedSchema {
@Model
final class Job {
- let id: UUID = UUID()
+ var id: UUID = UUID()
var name: String = ""
var color: JobColor = JobColor.red
var salaryType: JobSalaryType = JobSalaryType.hourly
@@ -57,7 +57,7 @@ enum JobSchemaV1: VersionedSchema {
@Model
final class OneTimeJob {
- let id: UUID = UUID()
+ var id: UUID = UUID()
var name: String = ""
var date: Date = Date()
var salary: Int = 0
diff --git a/JShift/Views/ContentView.swift b/JShift/Views/ContentView.swift
index 0763ce8..8264bb1 100644
--- a/JShift/Views/ContentView.swift
+++ b/JShift/Views/ContentView.swift
@@ -4,7 +4,7 @@ struct ContentView: View {
@State private var selectedTab: Tab = .shift
@State private var isWelcomePresented = false
@Environment(\.openURL) private var openURL
- private let AVAIABLE_OB_VERSION = "4"
+ private let AVAIABLE_OB_VERSION = "5"
var body: some View {
TabView(selection: $selectedTab) {
@@ -39,13 +39,12 @@ struct ContentView: View {
title: "アップデート内容",
detailText: "",
bulletedListItems: [
- .init(title: "チャート", description: "年間給与のチャートを復活させました。", symbolName: "chart.bar.xaxis.ascending", tintColor: UIColor(.green)),
- .init(title: "給与表示", description: "給与の表示順を給与の高い順に変更しました。", symbolName: "arrow.up.arrow.down", tintColor: UIColor(.blue)),
+ .init(title: "iOS 26に対応", description: "iOS 26対応と軽微な不具合の修正", symbolName: "apple.logo", tintColor: UIColor(.green)),
],
boldButtonItem: .init(title: "続ける", action: {
isWelcomePresented = false
}),
- linkButtonItem: .init(title: "詳細", action: { openURL(URL(string: "https://github.com/shinking02/JShift/commit/2bb25dfe5a226385cea768bd6562368fe5018ade")!) })
+ linkButtonItem: .init(title: "詳細", action: { openURL(URL(string: "https://github.com/shinking02/JShift/pull/12")!) })
)
}
)
diff --git a/JShift/Views/Salary/SalaryContentView.swift b/JShift/Views/Salary/SalaryContentView.swift
index 8c1aee9..95256d6 100644
--- a/JShift/Views/Salary/SalaryContentView.swift
+++ b/JShift/Views/Salary/SalaryContentView.swift
@@ -60,7 +60,7 @@ struct SalaryContentView: View {
.cornerRadius(3)
.foregroundStyle(Color.secondary)
}
- .animation(.none)
+ .animation(nil, value: salaryData)
.frame(height: 260)
.listRowBackground(Color.clear)
.chartBackground { chartProxy in
@@ -105,3 +105,4 @@ struct SalaryContentView: View {
}
}
}
+
diff --git a/JShift/Views/Setting/SettingView.swift b/JShift/Views/Setting/SettingView.swift
index 3e9dc12..d180ec9 100644
--- a/JShift/Views/Setting/SettingView.swift
+++ b/JShift/Views/Setting/SettingView.swift
@@ -27,7 +27,7 @@ struct SettingView: View {
}
}
Section(footer:
- Text("© 2024 Shin Kawakami")
+ Text("© 2024-2025 Shin Kawakami")
.frame(maxWidth: .infinity, alignment: .center)
.foregroundStyle(.secondary)
) {
diff --git a/JShift/Views/Shift/ShiftSheetView.swift b/JShift/Views/Shift/DateShiftView.swift
similarity index 80%
rename from JShift/Views/Shift/ShiftSheetView.swift
rename to JShift/Views/Shift/DateShiftView.swift
index 2fb8aa2..97e748f 100644
--- a/JShift/Views/Shift/ShiftSheetView.swift
+++ b/JShift/Views/Shift/DateShiftView.swift
@@ -2,7 +2,7 @@ import RealmSwift
import SwiftData
import SwiftUI
-struct ShiftSheetView: View {
+struct DateShiftView: View {
@Binding var selectedDate: Date
@Query(sort: \Job.order) private var jobs: [Job]
@Query private var otJobs: [OneTimeJob]
@@ -35,15 +35,65 @@ struct ShiftSheetView: View {
private var dateOtJobs: [OneTimeJob] {
otJobs.filter { $0.date.isSameDay(selectedDate) }
}
- private var paymentDayJobs: [Job] {
- jobs.filter { job in
+ private var paymentDayJobsWithSalary: [(job: Job, salary: Int)] {
+ let salaryDataByJob = Dictionary(
+ uniqueKeysWithValues: SalaryManager.shared
+ .getSalaryData(date: selectedDate, jobs: jobs, dateMode: .month)
+ .map { ($0.job.id, $0) }
+ )
+
+ return jobs.compactMap { job in
+ guard job.displayPaymentDay else { return nil }
let paymentDay = job.getPaymentDay(year: selectedDate.year, month: selectedDate.month)
- return paymentDay.isSameDay(selectedDate) && job.displayPaymentDay
+ guard paymentDay.isSameDay(selectedDate) else { return nil }
+ guard let salaryData = salaryDataByJob[job.id] else { return nil }
+ let amountInt: Int
+ if salaryData.isConfirmed {
+ amountInt = Int(salaryData.confirmedSalary)
+ } else {
+ amountInt = Int(salaryData.forecastSalary)
+ }
+ guard amountInt > 0 else { return nil }
+ return (job: job, salary: amountInt)
}
}
var body: some View {
NavigationStack {
+ HStack {
+ Text("\(selectedDate.toString(.weekday))")
+ .font(.title3.bold())
+ Spacer()
+ HStack {
+ Button(
+ action: {
+ showOTJobAddSheet = true
+ },
+ label: {
+ Image(systemName: "plus.circle.dashed")
+ Text("単発")
+ }
+ )
+ .controlSize(.mini)
+ .buttonStyle(.borderedProminent)
+ .buttonBorderShape(.capsule)
+ Spacer().frame(width: 8)
+ Button(
+ action: {
+ showAddEventSheet = true
+ },
+ label: {
+ Image(systemName: "plus.circle")
+ Text("長期")
+ }
+ )
+ .controlSize(.mini)
+ .buttonStyle(.borderedProminent)
+ .buttonBorderShape(.capsule)
+ .disabled(jobs.isEmpty)
+ }
+ }
+ .padding(.horizontal, 16)
ScrollView {
ForEach(dateEvents) { event in
Group {
@@ -66,14 +116,13 @@ struct ShiftSheetView: View {
}
.padding(.horizontal)
}
- ForEach(paymentDayJobs) { job in
+ ForEach(paymentDayJobsWithSalary, id: \.job.id) { paymentDayJob in
Group {
- Divider()
- PaymentDayRowView(job: job, date: selectedDate)
+ PaymentDayRowView(job: paymentDayJob.job, date: selectedDate, salary: paymentDayJob.salary)
}
.padding(.horizontal)
}
- if dateEvents.isEmpty && dateOtJobs.isEmpty && paymentDayJobs.isEmpty && suggestedEvents.isEmpty{
+ if dateEvents.isEmpty && dateOtJobs.isEmpty && paymentDayJobsWithSalary.isEmpty && suggestedEvents.isEmpty{
Divider()
Text("予定がありません")
.bold()
@@ -104,33 +153,6 @@ struct ShiftSheetView: View {
await CalendarManager.shared.syncGoogleCalendar(skipSyncCalendarList: true)
}
.frame(maxWidth: .infinity)
- .toolbar {
- ToolbarItem(placement: .topBarLeading) {
- Text("\(selectedDate.toString(.weekday))")
- .font(.title3.bold())
- }
- ToolbarItem(placement: .topBarTrailing) {
- Button(
- action: {
- showOTJobAddSheet = true
- },
- label: {
- Image("custom.pencil.and.list.clipboard.badge.plus")
- }
- )
- }
- ToolbarItem(placement: .topBarTrailing) {
- Button(
- action: {
- showAddEventSheet = true
- },
- label: {
- Image(systemName: "plus")
- }
- )
- .disabled(jobs.isEmpty)
- }
- }
}
.onChange(of: selectedDate) {
suggestedEvents = getSuggestEvents(selectedDate)
diff --git a/JShift/Views/Shift/Parts/CalendarView.swift b/JShift/Views/Shift/Parts/CalendarView.swift
index aa752e3..bd81e49 100644
--- a/JShift/Views/Shift/Parts/CalendarView.swift
+++ b/JShift/Views/Shift/Parts/CalendarView.swift
@@ -133,7 +133,12 @@ struct CalendarView: UIViewRepresentable {
let paymentDayJob = parent.jobs.first { $0.getPaymentDay(year: dateComponents.year ?? 0, month: dateComponents.month ?? 0).isSameDay(dateComponents.date ?? Date()) && $0.displayPaymentDay }
if let paymentDayJob = paymentDayJob {
- return createCustomDecoration(dayJob: dayJob, dayOTJobs: dayOTJobs, paymentDayJob: paymentDayJob, dateEvents: dateEvents)
+ let paymentJobSalary = SalaryManager.shared
+ .getSalaryData(date: dateComponents.date ?? Date(), jobs: [paymentDayJob], dateMode: .month)
+ .first
+ if let paymentJobSalary = paymentJobSalary, (paymentJobSalary.confirmedSalary > 0 || paymentJobSalary.forecastSalary > 0) {
+ return createCustomDecoration(dayJob: dayJob, dayOTJobs: dayOTJobs, paymentDayJob: paymentDayJob, dateEvents: dateEvents)
+ }
}
if let dayJob = dayJob {
return .default(color: UIColor(dayJob.color.toColor()))
@@ -152,6 +157,7 @@ struct CalendarView: UIViewRepresentable {
UIImage(named: "custom.yensign.badge", in: nil, with: UIImage.SymbolConfiguration(paletteColors: [UIColor(.secondary), UIColor(paymentDayJob.color.toColor())])), size: .large
)
}
+
return .image(UIImage(systemName: "yensign"), color: UIColor(paymentDayJob.color.toColor()), size: .large)
}
diff --git a/JShift/Views/Shift/Parts/PaymentDayRowView.swift b/JShift/Views/Shift/Parts/PaymentDayRowView.swift
index ec547ae..a240774 100644
--- a/JShift/Views/Shift/Parts/PaymentDayRowView.swift
+++ b/JShift/Views/Shift/Parts/PaymentDayRowView.swift
@@ -4,30 +4,25 @@ import SwiftUI
struct PaymentDayRowView: View {
let job: Job
let date: Date
- @State private var salary = 0
+ let salary: Int
@ViewBuilder
var body: some View {
- if salary > 0 {
- HStack(alignment: .center) {
- Rectangle()
- .frame(width: 4, height: 32)
- .cornerRadius(2)
- .foregroundStyle(job.color.toColor())
- Text("\(job.name)給料日")
- .bold()
- .lineLimit(1)
- Spacer()
- Text("\(salary)円")
- .lineLimit(2)
- .font(.caption)
- .foregroundStyle(.secondary)
- .multilineTextAlignment(.center)
- }
- .onAppear {
- let salaryData = SalaryManager.shared.getSalaryData(date: date, jobs: [job], dateMode: .month).first!
- salary = salaryData.isConfirmed ? salaryData.confirmedSalary : salaryData.forecastSalary
- }
+ Divider()
+ HStack(alignment: .center) {
+ Rectangle()
+ .frame(width: 4, height: 32)
+ .cornerRadius(2)
+ .foregroundStyle(job.color.toColor())
+ Text("\(job.name)給料日")
+ .bold()
+ .lineLimit(1)
+ Spacer()
+ Text("\(salary)円")
+ .lineLimit(2)
+ .font(.caption)
+ .foregroundStyle(.secondary)
+ .multilineTextAlignment(.center)
}
}
}
diff --git a/JShift/Views/Shift/ShiftView.swift b/JShift/Views/Shift/ShiftView.swift
index 705de33..0f8e361 100644
--- a/JShift/Views/Shift/ShiftView.swift
+++ b/JShift/Views/Shift/ShiftView.swift
@@ -23,6 +23,7 @@ struct ShiftView: View {
)
.frame(height: 470)
Spacer()
+ DateShiftView(selectedDate: $selectedDate)
}
.onAppear {
if isInitial && !isWelcomePresented {
@@ -48,16 +49,6 @@ struct ShiftView: View {
}
}
}
- .sheet(isPresented: $isSheetPresented) {
- ShiftSheetView(selectedDate: $selectedDate)
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
- .presentationDetents([.height(240), .large])
- .presentationCornerRadius(18)
- .presentationBackground(.bar)
- .presentationBackgroundInteraction(.enabled(upThrough: .large))
- .interactiveDismissDisabled()
- .bottomMaskForSheet()
- }
}
}
}