Skip to content

Commit

Permalink
Allow to disable image resizing when uploading attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
stigger committed Nov 30, 2023
1 parent 0ca42f7 commit 8605d1b
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 9 deletions.
1 change: 1 addition & 0 deletions Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"preferences.notifications.include-pictures" = "Include pictures";
"preferences.notifications.grouping" = "Group follow, favourite, and boost notifications";
"preferences.notifications.sounds" = "Sounds";
"preferences.optimize-images-before-upload" = "Optimize images before upload";
"preferences.muted-users" = "Muted Users";
"preferences.home-timeline-position-on-startup" = "Home timeline position on startup";
"preferences.notifications-position-on-startup" = "Notifications position on startup";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ enum AltTextError: String, Error {
public enum MediaProcessingService {}

public extension MediaProcessingService {
static func dataAndMimeType(itemProvider: NSItemProvider) -> AnyPublisher<(data: InputStream, mimeType: String), Error> {
static func dataAndMimeType(itemProvider: NSItemProvider, optimizeImages: Bool) -> AnyPublisher<(data: InputStream, mimeType: String), Error> {
let registeredTypes = itemProvider.registeredTypeIdentifiers.compactMap(UTType.init)

let mimeType: String
Expand All @@ -47,10 +47,10 @@ public extension MediaProcessingService {
return uploadableMimeTypes.contains(mimeType)
}), let preferredMIMEType = type.preferredMIMEType {
mimeType = preferredMIMEType
dataPublisher = fileRepresentationDataPublisher(itemProvider: itemProvider, type: type)
dataPublisher = fileRepresentationDataPublisher(itemProvider: itemProvider, type: type, optimizeImages: optimizeImages)
} else if registeredTypes == [UTType.image], let pngMIMEType = UTType.png.preferredMIMEType { // screenshot
mimeType = pngMIMEType
dataPublisher = UIImagePNGDataPublisher(itemProvider: itemProvider)
dataPublisher = UIImagePNGDataPublisher(itemProvider: itemProvider, optimize: optimizeImages)
} else {
return Fail(error: MediaProcessingError.invalidMimeType).eraseToAnyPublisher()
}
Expand Down Expand Up @@ -105,15 +105,16 @@ private extension MediaProcessingService {
] as [CFString: Any] as CFDictionary

static func fileRepresentationDataPublisher(itemProvider: NSItemProvider,
type: UTType) -> AnyPublisher<InputStream, Error> {
type: UTType,
optimizeImages: Bool) -> AnyPublisher<InputStream, Error> {
Future<InputStream, Error> { promise in
itemProvider.loadFileRepresentation(forTypeIdentifier: type.identifier) { url, error in
if let error = error {
promise(.failure(error))
} else if let url = url {
promise(Result {
if type.conforms(to: .image) && type != .gif {
return try imageData(url: url, type: type)
return try imageData(url: url, type: type, optimize: optimizeImages)
} else {
guard let stream = InputStream(url: url) else { throw MediaProcessingError.fileURLNotFound }
// The temporary file will be removed upon return. Opening a stream gives us a file descriptor, which allows
Expand All @@ -130,7 +131,7 @@ private extension MediaProcessingService {
.eraseToAnyPublisher()
}

static func UIImagePNGDataPublisher(itemProvider: NSItemProvider) -> AnyPublisher<InputStream, Error> {
static func UIImagePNGDataPublisher(itemProvider: NSItemProvider, optimize: Bool) -> AnyPublisher<InputStream, Error> {
#if canImport(UIKit)
return Future<InputStream, Error> { promise in
itemProvider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { item, error in
Expand All @@ -143,7 +144,7 @@ private extension MediaProcessingService {

try data.write(to: url)

return try imageData(url: url, type: .png)
return try imageData(url: url, type: .png, optimize: optimize)
})
} else {
promise(.failure(MediaProcessingError.imageNotFound))
Expand All @@ -156,7 +157,11 @@ private extension MediaProcessingService {
#endif
}

static func imageData(url: URL, type: UTType) throws -> InputStream {
static func imageData(url: URL, type: UTType, optimize: Bool) throws -> InputStream {
if !optimize, let stream = InputStream(url: url) {
stream.open()
return stream
}
guard let source = CGImageSourceCreateWithURL(url as CFURL, Self.imageSourceOptions) else {
throw MediaProcessingError.unableToCreateImageSource
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ public extension AppPreferences {
}
set { self[.postingLanguages] = newValue }
}

var optimizeImagesBeforeUpload: Bool {
get { self[.optimizeImagesBeforeUpload] ?? true }
set { self[.optimizeImagesBeforeUpload] = newValue }
}
}

private extension AppPreferences {
Expand Down Expand Up @@ -288,6 +293,7 @@ private extension AppPreferences {
case useMediaDescriptionMetadata
case visibilityIconColors
case postingLanguages
case optimizeImagesBeforeUpload
}

subscript<T>(index: Item) -> T? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public extension CompositionViewModel {

func attach(itemProviders: [NSItemProvider], parentViewModel: ComposeStatusViewModel) {
Publishers.MergeMany(itemProviders.map {
MediaProcessingService.dataAndMimeType(itemProvider: $0)
MediaProcessingService.dataAndMimeType(itemProvider: $0, optimizeImages: identityContext.appPreferences.optimizeImagesBeforeUpload)
.zip(
identityContext.appPreferences.useMediaDescriptionMetadata
? MediaProcessingService.description(itemProvider: $0)
Expand Down
4 changes: 4 additions & 0 deletions Views/SwiftUI/Preferences/AppPreferencesSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ struct AppPreferencesSection: View {
}
}
}
Group {
Toggle("preferences.optimize-images-before-upload",
isOn: $identityContext.appPreferences.optimizeImagesBeforeUpload)
}
}
Section(header: Text("preferences.app.advanced")) {
Picker("preferences.api-compatibility-mode", selection: Binding<APICompatibilityMode?>(
Expand Down

0 comments on commit 8605d1b

Please sign in to comment.