Skip to main content

allow toggling favorite status

ID
0e1eaa6
date
2023-05-13 13:14:58+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
ac5741b
message
allow toggling favorite status
changed files
7 files, 126 additions, 2 deletions

Changed files

actions/get_structural_metadata.swift (1400) → actions/get_structural_metadata.swift (1444)

diff --git a/actions/get_structural_metadata.swift b/actions/get_structural_metadata.swift
index dcd0075..37c9ca9 100644
--- a/actions/get_structural_metadata.swift
+++ b/actions/get_structural_metadata.swift
@@ -31,6 +31,7 @@ PHAssetCollection
 struct AssetData: Codable {
   var localIdentifier: String
   var creationDate: String?
+  var isFavorite: Bool
 }
 
 var allAssets: [AssetData] = []
@@ -38,11 +39,11 @@ var allAssets: [AssetData] = []
 PHAsset
   .fetchAssets(with: PHAssetMediaType.image, options: nil)
   .enumerateObjects({ (asset, _, _) in
-    print(asset)
     allAssets.append(
       AssetData(
         localIdentifier: asset.localIdentifier,
-        creationDate: asset.creationDate?.ISO8601Format()
+        creationDate: asset.creationDate?.ISO8601Format(),
+        isFavorite: asset.isFavorite
       )
     )
   })

actions/run_action.swift (0) → actions/run_action.swift (1951)

diff --git a/actions/run_action.swift b/actions/run_action.swift
new file mode 100644
index 0000000..9efb986
--- /dev/null
+++ b/actions/run_action.swift
@@ -0,0 +1,76 @@
+#!/usr/bin/env swift
+
+import Photos
+
+func getAlbumWith(name: String) -> PHAssetCollection {
+  let collections =
+    PHAssetCollection
+    .fetchAssetCollections(with: .album, subtype: .albumRegular, options: nil)
+
+  var thisAssetCollection: PHAssetCollection? = nil
+
+  collections.enumerateObjects({ (album, index, stop) in
+    let assetCollection = album
+
+    if assetCollection.localizedTitle == Optional(name) {
+      thisAssetCollection = assetCollection
+    }
+  })
+
+  if thisAssetCollection != nil {
+    return thisAssetCollection!
+  } else {
+    fputs("Unable to find album with name: \(name).\n", stderr)
+    exit(1)
+  }
+}
+
+func getPhotoWith(uuid: String) -> PHAsset {
+  let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [uuid], options: nil)
+
+  if fetchResult.count == 1 {
+    return fetchResult.firstObject!
+  } else {
+    fputs("Unable to find photo with ID: \(uuid).\n", stderr)
+    exit(1)
+  }
+}
+
+let arguments = CommandLine.arguments
+
+guard arguments.count == 3 else {
+  fputs("Usage: \(arguments[0]) PHOTO_ID ACTION\n", stderr)
+  exit(1)
+}
+
+let action = arguments[2]
+
+let flagged = getAlbumWith(name: "Flagged")
+let rejected = getAlbumWith(name: "Rejected")
+let needsAction = getAlbumWith(name: "Needs Action")
+
+let photo = getPhotoWith(uuid: arguments[1])
+
+try PHPhotoLibrary.shared().performChangesAndWait {
+
+
+  if action == "toggle-favorite" {
+    let request = PHAssetChangeRequest(for: photo)
+    request.isFavorite = !photo.isFavorite
+  }
+}
+
+// try PHPhotoLibrary.shared().performChangesAndWait {
+//   let changeFlagged =
+//     PHAssetCollectionChangeRequest(for: flagged)!
+//   let changeRejected =
+//     PHAssetCollectionChangeRequest(for: rejected)!
+//   let changeNeedsAction =
+//     PHAssetCollectionChangeRequest(for: needsAction)!
+//
+//   let assets = [photo] as NSFastEnumeration
+//
+//   changeFlagged.addAssets(assets)
+//   changeRejected.removeAssets(assets)
+//   changeNeedsAction.removeAssets(assets)
+// }

remove_image_from_album.swift (1689) → remove_image_from_album.swift (1691)

diff --git a/remove_image_from_album.swift b/remove_image_from_album.swift
index 6bd4d9e..9b4db30 100644
--- a/remove_image_from_album.swift
+++ b/remove_image_from_album.swift
@@ -63,3 +63,4 @@ try PHPhotoLibrary.shared().performChangesAndWait {
 
   request!.removeAssets([photo] as NSFastEnumeration)
 }
+[]
\ No newline at end of file

server.py (5461) → server.py (6041)

diff --git a/server.py b/server.py
index 9475a42..b20d042 100755
--- a/server.py
+++ b/server.py
@@ -57,6 +57,14 @@ class PhotosData:
 
         return render_template('index.html', assets=all_assets, position=position, prev_five=prev_five, this_asset=this_asset, next_five=next_five)
 
+    def toggle_favorite(self, local_identifier):
+        subprocess.check_call(['swift', 'actions/run_action.swift', local_identifier, 'toggle-favorite'])
+
+        this_asset = self.all_assets[self.all_positions[local_identifier]]
+        this_asset['isFavorite'] = not this_asset['isFavorite']
+
+        self.get_response.cache_clear()
+
     def flag(self, local_identifier):
         subprocess.check_call(['swift', 'scripts/flag.swift', local_identifier])
 
@@ -183,6 +191,15 @@ def needs_action():
     return _perform_action(request, photos_data.needs_action)
 
 
+@app.route('/actions/toggle_favorite')
+def toggle_favorite():
+    local_identifier = request.args['localIdentifier']
+
+    photos_data.toggle_favorite(local_identifier)
+
+    return redirect(url_for('index', localIdentifier=local_identifier))
+
+
 @app.route('/image')
 def image():
     local_identifier = request.args['localIdentifier']

static/style.css (0) → static/style.css (291)

diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..2d47fd2
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,17 @@
+.favorite {
+  text-align: right;
+  position: absolute;
+  z-index: 10000;
+  margin-top: 53px;
+  margin-left: 47px;
+  color: white;
+  display: inline;
+  text-shadow: 0px 0px 3px black;
+  line-height: 0px;
+}
+
+.this_asset .favorite {
+  font-size: 21px;
+  margin-top: 69px;
+  margin-left: 61px;
+}
\ No newline at end of file

templates/index.html (7942) → templates/index.html (8145)

diff --git a/templates/index.html b/templates/index.html
index ad4a00c..348b4dd 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -1,3 +1,7 @@
+<head>
+  <link rel="stylesheet" href="/static/style.css">
+</head>
+
 <style>
   body {
     text-align: center;
@@ -205,6 +209,9 @@ document.onkeydown = function(e) {
   } else if (e.key === "3") {
     window.location = "/actions/needs_action?localIdentifier={{ this_asset['localIdentifier'] }}";
   }
+  else if (e.key === "f") {
+     window.location = "/actions/toggle_favorite?localIdentifier={{ this_asset['localIdentifier'] }}";
+   }
 }
 </script>
 

templates/thumbnail.html (579) → templates/thumbnail.html (665)

diff --git a/templates/thumbnail.html b/templates/thumbnail.html
index 98c4711..229bb16 100644
--- a/templates/thumbnail.html
+++ b/templates/thumbnail.html
@@ -7,6 +7,11 @@
     {% elif asset['state'] == 'Needs Action' %}
       <div class="state">ℹ</div>
     {% endif %}
+
+    {% if asset.isFavorite %}
+      <div class="favorite">♥</div>
+    {% endif %}
+
     <img
       src="{{ url_for('thumbnail', localIdentifier=asset['localIdentifier']) }}"
       class="thumbnail state-{{ asset['state'] | replace(' ', '-')  }}">