copy/paste events

This commit is contained in:
Selim Mustafaev 2021-02-14 14:40:07 +03:00
parent 40703f4038
commit bd1f7a67be
42 changed files with 151 additions and 25 deletions

View File

@ -847,7 +847,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 66;
CURRENT_PROJECT_VERSION = 67;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -870,7 +870,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 66;
CURRENT_PROJECT_VERSION = 67;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

@ -1,109 +1,109 @@
{
"images" : [
{
"filename" : "wheel-40.png",
"filename" : "wheel2-40.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "wheel-60.png",
"filename" : "wheel2-60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "wheel-58.png",
"filename" : "wheel2-58.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "wheel-87.png",
"filename" : "wheel2-87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "wheel-80.png",
"filename" : "wheel2-80.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "wheel-120.png",
"filename" : "wheel2-120.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "wheel-121.png",
"filename" : "wheel2-121.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "wheel-180.png",
"filename" : "wheel2-180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "wheel-20.png",
"filename" : "wheel2-20.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "wheel-41.png",
"filename" : "wheel2-41.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "wheel-29.png",
"filename" : "wheel2-29.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "wheel-59.png",
"filename" : "wheel2-59.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "wheel-42.png",
"filename" : "wheel2-42.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "wheel-81.png",
"filename" : "wheel2-81.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "wheel-76.png",
"filename" : "wheel2-76.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "wheel-152.png",
"filename" : "wheel2-152.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "wheel-167.png",
"filename" : "wheel2-167.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "wheel-1024.png",
"filename" : "wheel2-1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -4,6 +4,7 @@ import RxSwift
import Realm
import RealmSwift
import PKHUD
import MobileCoreServices
class EventPin: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
@ -46,6 +47,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
let bag = DisposeBag()
var modeButton: UIBarButtonItem!
var addButton: UIBarButtonItem!
var pasteButton: UIBarButtonItem!
var mode: EventsMode = .map
public var vehicle: Vehicle? {
@ -69,12 +71,18 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
self.modeButton = UIBarButtonItem(image: UIImage(systemName: "list.bullet"), style: .plain, target: self, action: #selector(switchMode(_:)))
self.addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addEvent(_:)))
self.navigationItem.rightBarButtonItems = [self.modeButton, self.addButton]
self.pasteButton = UIBarButtonItem(image: UIImage(systemName: "doc.on.clipboard"), style: .plain, target: self, action: #selector(pasteEvent(_:)))
self.setupBarButtonItems()
self.map.delegate = self
self.updateInterface()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.setupBarButtonItems()
}
func updateInterface() {
if let vehicle = self.vehicle {
self.pins = vehicle.events.map(EventPin.init(event:))
@ -129,6 +137,14 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let copy = UIAction(title: NSLocalizedString("Copy", comment: ""), image: UIImage(systemName: "doc.on.doc")) { action in
self.copyEvent(index: indexPath.row)
}
let share = UIAction(title: NSLocalizedString("Share", comment: ""), image: UIImage(systemName: "square.and.arrow.up")) { action in
self.shareEvent(index: indexPath.row)
}
let edit = UIAction(title: NSLocalizedString("Edit", comment: ""), image: UIImage(systemName: "pencil")) { action in
self.editEvent(index: indexPath.row)
}
@ -137,11 +153,18 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
self.deleteEvent(index: indexPath.row)
}
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: [edit, delete])
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: [copy, share, edit, delete])
}
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let copy = UIContextualAction(style: .normal, title: NSLocalizedString("Copy", comment: "")) { action, view, completion in
self.copyEvent(index: indexPath.row)
completion(true)
}
copy.image = UIImage(systemName: "doc.on.doc")
copy.backgroundColor = .systemBlue
let delete = UIContextualAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { action, view, completion in
self.deleteEvent(index: indexPath.row, completion: completion)
}
@ -154,7 +177,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
edit.image = UIImage(systemName: "pencil")
edit.backgroundColor = .systemBlue
let configuration = UISwipeActionsConfiguration(actions: [delete, edit])
let configuration = UISwipeActionsConfiguration(actions: [delete, edit, copy])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
@ -210,6 +233,45 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
self.navigationController?.pushViewController(controller, animated: true)
}
func copyEvent(index: Int) {
guard let vehicle = self.vehicle else {
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return
}
var items: [String: Any] = [:]
let event = vehicle.events[index]
if let url = event.getMapLink() {
items[kUTTypeURL as String] = url
//UIPasteboard.general.setValue(url, forPasteboardType: kUTTypeURL as String)
}
if let data = try? JSONEncoder().encode(event) {
items["pro.aliencat.vehicle.event"] = data
//UIPasteboard.general.setData(data, forPasteboardType: "pro.aliencat.vehicle.event")
}
if !items.isEmpty {
UIPasteboard.general.items = [items]
}
self.setupBarButtonItems()
}
func shareEvent(index: Int) {
guard let vehicle = self.vehicle else {
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return
}
let event = vehicle.events[index]
if let url = event.getMapLink() {
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
self.present(controller, animated: true)
}
}
@objc func addEvent(_ sender: UIBarButtonItem) {
guard let vehicle = self.vehicle else {
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
@ -234,6 +296,44 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
self.navigationController?.pushViewController(controller, animated: true)
}
@objc func pasteEvent(_ sender: UIBarButtonItem) {
guard let vehicle = self.vehicle else {
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return
}
guard let data = UIPasteboard.general.data(forPasteboardType: "pro.aliencat.vehicle.event") else { return }
do {
let event = try JSONDecoder().decode(VehicleEvent.self, from: data)
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .medium
let msg = formatter.string(from: Date(timeIntervalSince1970: event.date)) + "\n" + event.getLocationString()
let alert = UIAlertController(title: NSLocalizedString("Paste event", comment: "from clipboard"), message: msg, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("Paste", comment: "from clipboard"), style: .default, handler: { action in
HUD.show(.progress)
event.id = UUID().uuidString
Api.add(event: event, to: vehicle.getNumber())
.observeOn(MainScheduler.instance)
.subscribe(onSuccess: { self.update(vehicle: $0) }, onError:
{ error in
HUD.show(error: error)
})
.disposed(by: self.bag)
}))
alert.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil))
self.present(alert, animated: true)
} catch {
print(error)
}
}
func setupBarButtonItems() {
let pasteVisible = UIPasteboard.general.data(forPasteboardType: "pro.aliencat.vehicle.event") != nil
self.navigationItem.rightBarButtonItems = pasteVisible ? [self.modeButton, self.addButton, self.pasteButton] : [self.modeButton, self.addButton]
}
@discardableResult
func update(vehicle: Vehicle) -> Bool {
do {

View File

@ -48,6 +48,23 @@ class VehicleEvent: Object, Codable, Cloneable {
return ["plateNumber"]
}
func getMapLink() -> URL? {
var urlString = "http://maps.apple.com/?sll=\(self.latitude),\(self.longitude)"
if let address = self.address?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
urlString = urlString + "&address=" + address
}
return URL(string: urlString)
}
func getLocationString() -> String {
let coordinates = "Lat: \(self.latitude), Lon: \(self.longitude)"
if let addressString = self.address {
return "\(addressString) (\(coordinates)"
} else {
return coordinates
}
}
// MARK: - Cloneable
required init(copy: VehicleEvent) {

View File

@ -3,9 +3,9 @@ import Foundation
enum Constants {
static var baseUrl: String {
#if DEBUG
return "http://127.0.0.1:3000/"
//return "http://127.0.0.1:3000/"
//return "http://192.168.1.67:3000/"
//return "https://vps.aliencat.pro:8443/"
return "https://vps.aliencat.pro:8443/"
#else
return "https://vps.aliencat.pro:8443/"
#endif

View File

@ -91,6 +91,9 @@
/* No comment provided by engineer. */
"Contract series and number" = "Серия и номер договора";
/* No comment provided by engineer. */
"Copy" = "Копировать";
/* No comment provided by engineer. */
"Copy to pasteboard" = "Копировать в буфер обмена";
@ -238,6 +241,12 @@
/* No comment provided by engineer. */
"Owners" = "Владельцы";
/* from clipboard */
"Paste" = "Вставить";
/* from clipboard */
"Paste event" = "Вставить событие";
/* No comment provided by engineer. */
"Photos" = "Фотографии";