2022-01-30 18:27:20 +00:00
|
|
|
//
|
|
|
|
// QRCode.swift
|
|
|
|
// SimpleX
|
|
|
|
//
|
|
|
|
// Created by Evgeny Poberezkin on 30/01/2022.
|
|
|
|
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
import CoreImage.CIFilterBuiltins
|
2025-04-14 21:25:32 +01:00
|
|
|
import SimpleXChat
|
2022-01-30 18:27:20 +00:00
|
|
|
|
2022-11-21 08:37:13 +00:00
|
|
|
struct MutableQRCode: View {
|
|
|
|
@Binding var uri: String
|
2023-12-05 09:48:04 +00:00
|
|
|
var withLogo: Bool = true
|
|
|
|
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
|
2022-01-30 18:27:20 +00:00
|
|
|
|
|
|
|
var body: some View {
|
2023-12-05 09:48:04 +00:00
|
|
|
QRCode(uri: uri, withLogo: withLogo, tintColor: tintColor)
|
|
|
|
.id("simplex-qrcode-view-for-\(uri)")
|
2022-01-30 18:27:20 +00:00
|
|
|
}
|
2022-11-21 08:37:13 +00:00
|
|
|
}
|
2022-01-30 18:27:20 +00:00
|
|
|
|
2025-04-14 21:25:32 +01:00
|
|
|
struct SimpleXCreatedLinkQRCode: View {
|
|
|
|
let link: CreatedConnLink
|
|
|
|
@Binding var short: Bool
|
|
|
|
var onShare: (() -> Void)? = nil
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
QRCode(uri: link.simplexChatUri(short: short), onShare: onShare)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-17 12:56:12 +04:00
|
|
|
struct SimpleXLinkQRCode: View {
|
|
|
|
let uri: String
|
|
|
|
var withLogo: Bool = true
|
|
|
|
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
|
ios: rework UX of creating new connection (#3482)
* ios: connection UI (wip)
* custom search
* rework invite
* connect paste link ui
* scan rework, process errors, other fixes
* scan layout
* clear link on cancel
* improved search
* further improve search
* animation
* connect on paste in search
* layout
* layout
* layout
* layout, add conn
* delete unused invitation, create used invitation chat
* remove old views
* regular paste button
* new chat menu
* previews
* increase spacing
* animation, fix alerts
* swipe
* change text
* less sensitive gesture
* layout
* search cancel button transition
* slow down chat list animation (uses deprecated modifiers)
* icons
* update code scanner, layout
* manage camera permissions
* ask to delete unused invitation
* comment
* remove onDismiss
* don't filter chats on link in search, allow to paste text with link
* cleanup link after connection
* filter chat by link
* revert change
* show link descr
* disabled search
* underline
* filter own group
* simplify
* no animation
* add delay, move createInvitation
* update library
* possible fix for ios 15
* add explicit frame to qr code
* update library
* Revert "add explicit frame to qr code"
This reverts commit 95c7d31e47b3da39b5985cd57638885c45b77de1.
* remove comment
* fix pasteboardHasURLs, disable paste button based on it
* align help texts with changed button names
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
* update library
* Revert "fix pasteboardHasURLs, disable paste button based on it"
This reverts commit 46f63572e90dbf460faab9ce694181209712bd00.
* remove unused var
* restore disabled
* export localizations
---------
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
2023-12-29 16:29:49 +04:00
|
|
|
var onShare: (() -> Void)? = nil
|
2023-10-17 12:56:12 +04:00
|
|
|
|
|
|
|
var body: some View {
|
ios: rework UX of creating new connection (#3482)
* ios: connection UI (wip)
* custom search
* rework invite
* connect paste link ui
* scan rework, process errors, other fixes
* scan layout
* clear link on cancel
* improved search
* further improve search
* animation
* connect on paste in search
* layout
* layout
* layout
* layout, add conn
* delete unused invitation, create used invitation chat
* remove old views
* regular paste button
* new chat menu
* previews
* increase spacing
* animation, fix alerts
* swipe
* change text
* less sensitive gesture
* layout
* search cancel button transition
* slow down chat list animation (uses deprecated modifiers)
* icons
* update code scanner, layout
* manage camera permissions
* ask to delete unused invitation
* comment
* remove onDismiss
* don't filter chats on link in search, allow to paste text with link
* cleanup link after connection
* filter chat by link
* revert change
* show link descr
* disabled search
* underline
* filter own group
* simplify
* no animation
* add delay, move createInvitation
* update library
* possible fix for ios 15
* add explicit frame to qr code
* update library
* Revert "add explicit frame to qr code"
This reverts commit 95c7d31e47b3da39b5985cd57638885c45b77de1.
* remove comment
* fix pasteboardHasURLs, disable paste button based on it
* align help texts with changed button names
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
* update library
* Revert "fix pasteboardHasURLs, disable paste button based on it"
This reverts commit 46f63572e90dbf460faab9ce694181209712bd00.
* remove unused var
* restore disabled
* export localizations
---------
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
2023-12-29 16:29:49 +04:00
|
|
|
QRCode(uri: simplexChatLink(uri), withLogo: withLogo, tintColor: tintColor, onShare: onShare)
|
2023-10-17 12:56:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 08:37:13 +00:00
|
|
|
struct QRCode: View {
|
|
|
|
let uri: String
|
2023-02-06 11:45:56 +03:00
|
|
|
var withLogo: Bool = true
|
|
|
|
var tintColor = UIColor(red: 0.023, green: 0.176, blue: 0.337, alpha: 1)
|
ios: rework UX of creating new connection (#3482)
* ios: connection UI (wip)
* custom search
* rework invite
* connect paste link ui
* scan rework, process errors, other fixes
* scan layout
* clear link on cancel
* improved search
* further improve search
* animation
* connect on paste in search
* layout
* layout
* layout
* layout, add conn
* delete unused invitation, create used invitation chat
* remove old views
* regular paste button
* new chat menu
* previews
* increase spacing
* animation, fix alerts
* swipe
* change text
* less sensitive gesture
* layout
* search cancel button transition
* slow down chat list animation (uses deprecated modifiers)
* icons
* update code scanner, layout
* manage camera permissions
* ask to delete unused invitation
* comment
* remove onDismiss
* don't filter chats on link in search, allow to paste text with link
* cleanup link after connection
* filter chat by link
* revert change
* show link descr
* disabled search
* underline
* filter own group
* simplify
* no animation
* add delay, move createInvitation
* update library
* possible fix for ios 15
* add explicit frame to qr code
* update library
* Revert "add explicit frame to qr code"
This reverts commit 95c7d31e47b3da39b5985cd57638885c45b77de1.
* remove comment
* fix pasteboardHasURLs, disable paste button based on it
* align help texts with changed button names
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
* update library
* Revert "fix pasteboardHasURLs, disable paste button based on it"
This reverts commit 46f63572e90dbf460faab9ce694181209712bd00.
* remove unused var
* restore disabled
* export localizations
---------
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Co-authored-by: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com>
2023-12-29 16:29:49 +04:00
|
|
|
var onShare: (() -> Void)? = nil
|
2023-02-06 11:45:56 +03:00
|
|
|
@State private var image: UIImage? = nil
|
2023-12-05 09:48:04 +00:00
|
|
|
@State private var makeScreenshotFunc: () -> Void = {}
|
2022-01-30 18:27:20 +00:00
|
|
|
|
2022-11-21 08:37:13 +00:00
|
|
|
var body: some View {
|
|
|
|
ZStack {
|
|
|
|
if let image = image {
|
|
|
|
qrCodeImage(image)
|
2024-10-07 20:30:17 +03:00
|
|
|
GeometryReader { geo in
|
|
|
|
ZStack {
|
|
|
|
if withLogo {
|
|
|
|
let w = geo.size.width
|
|
|
|
Image("icon-light")
|
|
|
|
.resizable()
|
|
|
|
.scaledToFit()
|
|
|
|
.frame(width: w * 0.16, height: w * 0.16)
|
|
|
|
.frame(width: w * 0.165, height: w * 0.165)
|
|
|
|
.background(.white)
|
|
|
|
.clipShape(Circle())
|
|
|
|
}
|
2023-02-06 11:45:56 +03:00
|
|
|
}
|
2024-10-07 20:30:17 +03:00
|
|
|
.onAppear {
|
|
|
|
makeScreenshotFunc = {
|
|
|
|
let size = CGSizeMake(1024 / UIScreen.main.scale, 1024 / UIScreen.main.scale)
|
|
|
|
showShareSheet(items: [makeScreenshot(geo.frame(in: .local).origin, size)])
|
|
|
|
onShare?()
|
|
|
|
}
|
2023-12-05 09:48:04 +00:00
|
|
|
}
|
2024-10-07 20:30:17 +03:00
|
|
|
.frame(width: geo.size.width, height: geo.size.height)
|
2023-02-06 11:45:56 +03:00
|
|
|
}
|
2024-10-07 20:30:17 +03:00
|
|
|
} else {
|
|
|
|
Color.clear.aspectRatio(1, contentMode: .fit)
|
2023-02-06 11:45:56 +03:00
|
|
|
}
|
2022-11-21 08:37:13 +00:00
|
|
|
}
|
2023-12-05 09:48:04 +00:00
|
|
|
.onTapGesture(perform: makeScreenshotFunc)
|
2024-10-07 20:30:17 +03:00
|
|
|
.task { image = await generateImage(uri, tintColor: tintColor) }
|
2023-12-13 11:27:28 +00:00
|
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
2022-11-21 08:37:13 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-30 18:27:20 +00:00
|
|
|
|
2022-11-21 08:37:13 +00:00
|
|
|
private func qrCodeImage(_ image: UIImage) -> some View {
|
|
|
|
Image(uiImage: image)
|
|
|
|
.resizable()
|
|
|
|
.interpolation(.none)
|
|
|
|
.aspectRatio(1, contentMode: .fit)
|
|
|
|
.textSelection(.enabled)
|
|
|
|
}
|
2022-01-30 18:27:20 +00:00
|
|
|
|
2024-10-07 20:30:17 +03:00
|
|
|
private func generateImage(_ uri: String, tintColor: UIColor) async -> UIImage? {
|
2022-11-21 08:37:13 +00:00
|
|
|
let context = CIContext()
|
|
|
|
let filter = CIFilter.qrCodeGenerator()
|
|
|
|
filter.message = Data(uri.utf8)
|
|
|
|
if let outputImage = filter.outputImage,
|
|
|
|
let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
|
2023-12-05 09:48:04 +00:00
|
|
|
return UIImage(cgImage: cgImage).replaceColor(UIColor.black, tintColor)
|
2022-01-30 18:27:20 +00:00
|
|
|
}
|
2022-11-21 08:37:13 +00:00
|
|
|
return nil
|
2022-01-30 18:27:20 +00:00
|
|
|
}
|
|
|
|
|
2023-02-06 11:45:56 +03:00
|
|
|
extension View {
|
|
|
|
func makeScreenshot(_ origin: CGPoint? = nil, _ targetSize: CGSize? = nil) -> UIImage {
|
|
|
|
let controller = UIHostingController(rootView: self.edgesIgnoringSafeArea(.all))
|
|
|
|
let targetSize = targetSize ?? controller.view.intrinsicContentSize
|
|
|
|
let view = controller.view
|
|
|
|
view?.bounds = CGRect(origin: origin ?? .zero, size: targetSize)
|
|
|
|
view?.backgroundColor = .clear
|
|
|
|
let renderer = UIGraphicsImageRenderer(size: targetSize)
|
|
|
|
return renderer.image { _ in
|
|
|
|
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-30 18:27:20 +00:00
|
|
|
struct QRCode_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
|
|
|
QRCode(uri: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D")
|
|
|
|
}
|
|
|
|
}
|