Initial PoC of iPad grid

This commit is contained in:
Marcin Czachurski 2023-05-11 20:00:39 +02:00
parent 0ac6ad376f
commit 446fbd9b9e
6 changed files with 78 additions and 36 deletions

View File

@ -27,6 +27,7 @@
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */; };
F825F0C929F7A562008BD204 /* UserProfilePrivateAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F825F0C829F7A562008BD204 /* UserProfilePrivateAccountView.swift */; };
F825F0CB29F7CFC4008BD204 /* FollowRequestsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F825F0CA29F7CFC4008BD204 /* FollowRequestsView.swift */; };
F830C3CD2A07A4020005FEF8 /* WaterfallGrid in Frameworks */ = {isa = PBXBuildFile; productRef = F830C3CC2A07A4020005FEF8 /* WaterfallGrid */; };
F835082329BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
F835082429BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
F83CBEFB298298A1002972C8 /* ImageCarouselPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F83CBEFA298298A1002972C8 /* ImageCarouselPicture.swift */; };
@ -449,6 +450,7 @@
F8210DD92966BB7E001D9973 /* NukeUI in Frameworks */,
F89B5CC029D019B600549F2F /* HTMLString in Frameworks */,
F88BC52A29E046D700CE6141 /* WidgetsKit in Frameworks */,
F830C3CD2A07A4020005FEF8 /* WaterfallGrid in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -988,6 +990,7 @@
F88BC52629E0431D00CE6141 /* ServicesKit */,
F88BC52929E046D700CE6141 /* WidgetsKit */,
F88BC52C29E04BB600CE6141 /* EnvironmentKit */,
F830C3CC2A07A4020005FEF8 /* WaterfallGrid */,
);
productName = Vernissage;
productReference = F88C2468295C37B80006098B /* Vernissage.app */;
@ -1031,6 +1034,7 @@
F88E4D4B297EA4290057491A /* XCRemoteSwiftPackageReference "EmojiText" */,
F89B5CBE29D019B600549F2F /* XCRemoteSwiftPackageReference "HTMLString" */,
F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */,
F830C3CB2A07A4020005FEF8 /* XCRemoteSwiftPackageReference "WaterfallGrid" */,
);
productRefGroup = F88C2469295C37B80006098B /* Products */;
projectDirPath = "";
@ -1338,7 +1342,7 @@
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@ -1366,7 +1370,7 @@
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@ -1394,7 +1398,7 @@
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@ -1421,7 +1425,7 @@
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@ -1580,7 +1584,7 @@
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@ -1621,7 +1625,7 @@
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@ -1675,6 +1679,14 @@
minimumVersion = 12.0.0;
};
};
F830C3CB2A07A4020005FEF8 /* XCRemoteSwiftPackageReference "WaterfallGrid" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/paololeonardi/WaterfallGrid.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.0;
};
};
F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/dmrschmidt/QRCode";
@ -1717,6 +1729,11 @@
package = F8210DD32966BB7E001D9973 /* XCRemoteSwiftPackageReference "Nuke" */;
productName = NukeUI;
};
F830C3CC2A07A4020005FEF8 /* WaterfallGrid */ = {
isa = XCSwiftPackageProductDependency;
package = F830C3CB2A07A4020005FEF8 /* XCRemoteSwiftPackageReference "WaterfallGrid" */;
productName = WaterfallGrid;
};
F84625FA29FE393B002D3AF4 /* QRCode */ = {
isa = XCSwiftPackageProductDependency;
package = F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */;

View File

@ -11,6 +11,7 @@ import ClientKit
import ServicesKit
import EnvironmentKit
import WidgetsKit
import WaterfallGrid
struct StatusesView: View {
public enum ListType: Hashable {
@ -50,7 +51,7 @@ struct StatusesView: View {
@State private var state: ViewState = .loading
@State private var lastStatusId: String?
private let defaultLimit = 20
private let defaultLimit = 40
private let imagePrefetcher = ImagePrefetcher(destination: .diskCache)
var body: some View {
@ -88,26 +89,35 @@ struct StatusesView: View {
@ViewBuilder
private func list() -> some View {
ScrollView {
LazyVStack(alignment: .center) {
ForEach(self.statusViewModels, id: \.id) { item in
ImageRowAsync(statusViewModel: item)
}
if allItemsLoaded == false {
HStack {
Spacer()
LoadingIndicator()
.task {
do {
try await self.loadMoreStatuses()
} catch {
ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
}
}
Spacer()
}
}
WaterfallGrid(self.statusViewModels, id: \.id) { item in
ImageRowAsync(statusViewModel: item,
withAvatar: true,
imageScale: self.applicationState.showGridOnUserProfile ? .squareHalfWidth : .orginalFullWidth)
.padding(.top, -2)
}
.gridStyle(columns: 3, spacing: 4)
// .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
// LazyVStack(alignment: .center) {
// ForEach(self.statusViewModels, id: \.id) { item in
// ImageRowAsync(statusViewModel: item)
// }
//
// if allItemsLoaded == false {
// HStack {
// Spacer()
// LoadingIndicator()
// .task {
// do {
// try await self.loadMoreStatuses()
// } catch {
// ErrorService.shared.handle(error, message: "statuses.error.loadingStatusesFailed", showToastr: !Task.isCancelled)
// }
// }
// Spacer()
// }
// }
// }
}
.refreshable {
do {

View File

@ -11,6 +11,7 @@ import ClientKit
import ServicesKit
import EnvironmentKit
import WidgetsKit
import WaterfallGrid
struct UserProfileStatusesView: View {
@EnvironmentObject private var applicationState: ApplicationState
@ -22,7 +23,7 @@ struct UserProfileStatusesView: View {
@State private var firstLoadFinished = false
@State private var statusViewModels: [StatusModel] = []
private let defaultLimit = 20
private let defaultLimit = 40
private let imagePrefetcher = ImagePrefetcher(destination: .diskCache)
private let singleGrids = [GridItem(.flexible(), spacing: 10)]
private let dubleGrid = [GridItem(.flexible(), spacing: 10), GridItem(.flexible(), spacing: 0)]
@ -54,7 +55,19 @@ struct UserProfileStatusesView: View {
.padding(.bottom, 8)
}
}
WaterfallGrid(self.statusViewModels, id: \.id) { item in
ImageRowAsync(statusViewModel: item,
withAvatar: false,
imageScale: self.applicationState.showGridOnUserProfile ? .squareHalfWidth : .orginalFullWidth)
// .if(self.applicationState.showGridOnUserProfile) {
// $0.frame(width: UIScreen.main.bounds.width / 2, height: UIScreen.main.bounds.width / 2)
// }
}
.gridStyle(columns: 3, spacing: 2)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
/*
LazyVGrid(columns: self.applicationState.showGridOnUserProfile ? dubleGrid : singleGrids, spacing: 5) {
ForEach(self.statusViewModels, id: \.id) { item in
ImageRowAsync(statusViewModel: item,
@ -80,6 +93,7 @@ struct UserProfileStatusesView: View {
}
}
}
*/
} else {
LoadingIndicator()
.onFirstAppear {

View File

@ -59,8 +59,8 @@ struct ImageRowAsync: View {
}
}
}
.if(self.imageScale == .orginalFullWidth) {
$0.frame(width: self.imageWidth, height: self.imageHeight)
.if(self.imageScale == .squareHalfWidth) {
$0.frame(width: self.imageWidth / 3, height: self.imageHeight / 3)
}
} else {
TabView(selection: $selected) {
@ -98,8 +98,8 @@ struct ImageRowAsync: View {
}
}
})
.if(self.imageScale == .orginalFullWidth) {
$0.frame(width: self.imageWidth, height: self.imageHeight)
.if(self.imageScale == .squareHalfWidth) {
$0.frame(width: self.imageWidth / 3, height: self.imageHeight / 3)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.overlay(CustomPageTabViewStyleView(pages: self.statusViewModel.mediaAttachments, currentId: $selected))

View File

@ -155,10 +155,11 @@ struct ImageRowItemAsync: View {
private func imageView(image: Image) -> some View {
image
.resizable()
.scaledToFill()
.if(self.imageScale == .squareHalfWidth) {
$0.frame(width: UIScreen.main.bounds.width / 2, height: UIScreen.main.bounds.width / 2).clipped()
}
//.aspectRatio(contentMode: .fill)
.aspectRatio(contentMode: .fit)
// .if(self.imageScale == .squareHalfWidth) {
// $0.frame(width: UIScreen.main.bounds.width / 4, height: UIScreen.main.bounds.width / 4).clipped()
// }
.onTapGesture(count: 2) {
Task {
// Update favourite in Pixelfed server.

View File

@ -159,7 +159,7 @@ public struct BaseComposeView: View {
}
.photosPicker(isPresented: $photosPickerVisible,
selection: $selectedItems,
maxSelectionCount: 4,
maxSelectionCount: self.applicationState.statusMaxMediaAttachments,
matching: .images)
.fileImporter(isPresented: $isFileImporterPresented,
allowedContentTypes: [.image],