Skip to content

Commit

Permalink
feat: wire cells upload images & videos previews
Browse files Browse the repository at this point in the history
  • Loading branch information
El-Fitz committed Feb 17, 2025
1 parent 6b15af1 commit 8f387e6
Show file tree
Hide file tree
Showing 71 changed files with 965 additions and 87 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/test_pr_changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ jobs:
WireAuthentication:
- 'WireAuthentication/**'
- 'wire-ios-mono.xcworkspace/xcshareddata/xcschemes/WireAuthenticationAll.xcscheme'
WireCells:
- 'WireCells/**'
- 'wire-ios-mono.xcworkspace/xcshareddata/xcschemes/WireCellsAll.xcscheme'
WireDebug:
- 'WireDebug/**'
- 'wire-ios-mono.xcworkspace/xcshareddata/xcschemes/WireDebugAll.xcscheme'
WireDomain:
- 'WireDomain/**'
WireLogging:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>
54 changes: 44 additions & 10 deletions WireCells/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,82 @@

import PackageDescription

let WireTestingPackage = Target.Dependency.product(name: "WireTestingPackage", package: "WireFoundation")

let package = Package(
name: "WireCells",
platforms: [.iOS(.v16), .macOS(.v12)],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "WireCellsAPI",
targets: ["API"]
targets: ["WireCellsAPI"]
),
.library(
name: "WireCellsBindings",
targets: ["Bindings"]
targets: ["WireCellsBindings"]
),
.library(
name: "WireCellsUI",
targets: ["WireCellsUI"]
),
],
dependencies: [
.package(url: "https://github.com/pydio/cells-sdk-swift.git", branch: "v5-dev"),
.package(url: "https://github.com/awslabs/aws-sdk-swift.git", from: "1.0.0")
.package(url: "https://github.com/pydio/cells-sdk-swift.git", branch: "v0.1.1-alpha02"),
.package(url: "https://github.com/awslabs/aws-sdk-swift.git", from: "1.0.0"),
.package(name: "WireFoundation", path: "../WireFoundation"),
.package(name: "WireUI", path: "../WireUI")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "API",
name: "WireCellsAPI",
dependencies: [
.product(name: "CellsSDK", package: "cells-sdk-swift")
]
),
.target(name: "Bindings"),
.target(name: "WireCellsBindings"),
.target(
name: "Implementation",
name: "WireCellsImplementation",
dependencies: [
"API",
"WireCellsAPI",
.product(name: "AWSS3", package: "aws-sdk-swift"),
.product(name: "CellsSDK", package: "cells-sdk-swift")
]
),
.target(
name: "WireCellsUI",
dependencies: [
.product(name: "WireDesign", package: "WireUI")
]
),
.testTarget(
name: "WireCellsTests",
dependencies: [
"API",
"Implementation"
"WireCellsAPI",
"WireCellsImplementation"
]
),
.testTarget(
name: "WireCellsUITests",
dependencies: [
"WireCellsUI"
]
),
]
)

for target in package.targets {
if target.isTest {
target.dependencies += [WireTestingPackage]
}
}

for target in package.targets {
target.swiftSettings = (target.swiftSettings ?? []) + [
.enableUpcomingFeature("InternalImportsByDefault"),
.enableUpcomingFeature("FullTypedThrows"),
.enableUpcomingFeature("ExistentialAny")
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
//

public enum WireCellsFileQueryError: Error {
case genericError(Error)
case genericError(any Error)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@

public enum WireCellsFileUploadError: Error {
case fileTooLarge(fileSize: Int, maxSize: Int)
case genericError(Error)
case genericError(any Error)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import Foundation
public import Foundation

public struct WireCellsFileUploadInfo: Identifiable, Sendable {
public let data: Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

@preconcurrency import CellsSDK
import Foundation
@preconcurrency public import CellsSDK

public protocol WireCellsService {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import Foundation
public import Foundation

public struct WireCellsUploadedFile: Sendable {
/// The path of the uploaded file on the server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

class WireCellsAssembly {}
public class WireCellsAssembly {
public init() {
print("Init")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

package import Foundation
package import WireCellsAPI
package import CellsSDK

import AWSClientRuntime
@preconcurrency import AWSS3
import AWSSDKIdentity
@preconcurrency import CellsSDK
import ClientRuntime
import Foundation
import Smithy
import WireCellsAPI

package class WireCellsServiceImplementation: WireCellsService {

Expand Down Expand Up @@ -114,14 +115,14 @@ package class WireCellsServiceImplementation: WireCellsService {
}

private func _listFiles(atPath path: String) async throws(WireCellsFileQueryError) -> [RestNode] {
let request = RestLookupRequest()
var request = RestLookupRequest()
let locator = RestNodeLocator(path: path)
request.locators = RestNodeLocators(many: [locator])
let requestBuilder = NodeServiceAPI.lookupWithRequestBuilder(body: request, apiConfiguration: cellsApiConfig)

do {
let response: Response<RestNodeCollection> = try await requestBuilder.execute()
return response.body.nodes
return response.body.nodes ?? []
} catch {
throw .genericError(error)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import SwiftUI
import WireDesign

struct CircularIconButtonStyle: ButtonStyle {
private enum Constants {
static let backgroundColor: Color = BaseColorPalette.Neutrals.white.color
static let iconColor: Color = BaseColorPalette.Neutrals.black.color
static let strokeColor: Color = BaseColorPalette.Grays.gray40.color
static let strokeWidth: CGFloat = 1
}

let padding: CGFloat

func makeBody(configuration: Configuration) -> some View {
configuration
.label
.foregroundStyle(Constants.backgroundColor)
.overlay(Circle().stroke(Constants.strokeColor, lineWidth: Constants.strokeWidth).padding(padding))
.background(Circle().fill(Constants.iconColor).padding(padding))
// Optionally, apply a slight visual change when pressed
.opacity(configuration.isPressed ? 0.6 : 1.0)
}
}

#Preview {
Button(action: {
print("Tapped")
}, label: {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 24))
.buttonStyle(CircularIconButtonStyle(padding: 2))
})
.foregroundStyle(.white)
.frame(width: 35, height: 35)
.padding(20)
.background(Color.gray)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import SwiftUI
import WireDesign

struct DeleteItemButtonViewModifier: ViewModifier {
private enum Constants {
static let iconFontSize: CGFloat = 24
static let padding: CGFloat = 2
static let buttonSize: CGFloat = 35
static let offset: CGFloat = 17.5
}

let onRemove: @Sendable () -> Void

init(onRemove: @escaping @Sendable () -> Void) {
self.onRemove = onRemove
}

func body(content: Content) -> some View {
content
.overlay(alignment: .topTrailing) {
Button(action: {
onRemove()
}, label: {
Image(systemName: "xmark.circle.fill")
.font(.system(size: Constants.iconFontSize))
})
.buttonStyle(CircularIconButtonStyle(padding: Constants.padding))
.frame(
width: Constants.buttonSize,
height: Constants.buttonSize
)
.offset(
x: Constants.offset,
y: -Constants.offset
)
}
}
}

extension View {
func deleteItemButton(onRemove: @escaping @Sendable () -> Void) -> some View {
modifier(DeleteItemButtonViewModifier(onRemove: onRemove))
}
}

#Preview {
RoundedRectangle(cornerRadius: 10)
.fill(.gray)
.deleteItemButton(onRemove: {})
.frame(width: 200, height: 200)
}
49 changes: 49 additions & 0 deletions WireCells/Sources/WireCellsUI/Components/LocalImagePreview.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Wire
// Copyright (C) 2025 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import SwiftUI

struct LocalImagePreview: View {
private enum Constants {
static let cornerRadius: CGFloat = 10
}

let image: Image

var body: some View {
GeometryReader { geometry in
image
.resizable()
.scaledToFill()
// Image won't clip to the container's frame.
.frame(width: geometry.size.width, height: geometry.size.height)
.clipShape(RoundedRectangle(cornerRadius: Constants.cornerRadius, style: .circular))
}
}
}

#Preview {
VStack {
LocalImagePreview(image: Image("square-placeholder", bundle: .module))
.foregroundStyle(.black)
.frame(width: 200, height: 200)
.background(.white)
}
.padding()
.background(.gray)
}
Loading

0 comments on commit 8f387e6

Please sign in to comment.