{"action":"created","comment":{"url":"https://api.github.com/repos/mattrubin/authenticator/pulls/comments/45572746","id":45572746,"diff_hunk":"@@ -2,55 +2,83 @@\n //  TokenRowModel.swift\n //  Authenticator\n //\n-//  Copyright (c) 2015 Matt Rubin\n+//  Copyright (c) 2015 Authenticator authors\n //\n-//  Permission is hereby granted, free of charge, to any person obtaining a copy of\n-//  this software and associated documentation files (the \"Software\"), to deal in\n-//  the Software without restriction, including without limitation the rights to\n-//  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n-//  the Software, and to permit persons to whom the Software is furnished to do so,\n-//  subject to the following conditions:\n+//  Permission is hereby granted, free of charge, to any person obtaining a copy\n+//  of this software and associated documentation files (the \"Software\"), to deal\n+//  in the Software without restriction, including without limitation the rights\n+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+//  copies of the Software, and to permit persons to whom the Software is\n+//  furnished to do so, subject to the following conditions:\n //\n //  The above copyright notice and this permission notice shall be included in all\n //  copies or substantial portions of the Software.\n //\n //  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n-//  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n-//  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n-//  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n-//  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n+//  SOFTWARE.\n //\n \n import OneTimePassword\n \n-struct TokenRowModel {\n+struct TokenRowModel: Equatable {\n+    enum Action: Equatable {\n+        case UpdateKeychainItem(Token.KeychainItem)\n+        case EditKeychainItem(Token.KeychainItem)\n+        case CopyPassword(String)\n+    }\n+\n     let name, issuer, password: String\n     let showsButton: Bool\n-    let buttonAction: ()->()\n+    let buttonAction: Action\n+    let selectAction: Action\n+    let editAction: Action\n \n-    init(token: Token, buttonAction: ()->()) {\n-        name = token.name\n-        issuer = token.issuer\n-        password = token.currentPassword ?? \"\"\n-        if case .Counter = token.generator.factor {\n+    init(keychainItem: Token.KeychainItem) {\n+        name = keychainItem.token.name\n+        issuer = keychainItem.token.issuer\n+        password = keychainItem.token.currentPassword ?? \"\"\n+        if case .Counter = keychainItem.token.generator.factor {\n             showsButton = true\n         } else {\n             showsButton = false\n         }\n-        self.buttonAction = buttonAction\n+        buttonAction = .UpdateKeychainItem(keychainItem)\n+        selectAction = .CopyPassword(password)\n+        editAction = .EditKeychainItem(keychainItem)\n     }\n+}\n \n-    init() {\n-        (name, issuer, password) = (\"\", \"\", \"\")\n-        showsButton = false\n-        buttonAction = {}\n-    }\n+func == (lhs: TokenRowModel, rhs: TokenRowModel) -> Bool {\n+    return (lhs.name == rhs.name)\n+        && (lhs.issuer == rhs.issuer)\n+        && (lhs.password == rhs.password)\n+        && (lhs.showsButton == rhs.showsButton)\n+        && (lhs.buttonAction == rhs.buttonAction)\n+        && (lhs.selectAction == rhs.selectAction)\n+        && (lhs.editAction == rhs.editAction)\n+}\n \n-    func isVisuallyEquivalentToRowModel(rowModel: TokenRowModel) -> Bool {\n-        return (name == rowModel.name) &&\n-            (issuer == rowModel.issuer) &&\n-            (password == rowModel.password) &&\n-            (showsButton == rowModel.showsButton)\n+func == (lhs: TokenRowModel.Action, rhs: TokenRowModel.Action) -> Bool {\n+    switch (lhs, rhs) {\n+    case let (.UpdateKeychainItem(l), .UpdateKeychainItem(r)):\n+        return l == r\n+    case let (.EditKeychainItem(l), .EditKeychainItem(r)):\n+        return l == r\n+    case let (.CopyPassword(l), .CopyPassword(r)):\n+        return l == r\n+    default:\n+        return false\n     }\n }\n+\n+// TODO: Move keychain item equality into OneTimePassword","path":"Authenticator/Source/TokenRowModel.swift","position":108,"original_position":108,"commit_id":"25ccb58f91075df5c5ea9b2d1016b9b2ef209fa6","original_commit_id":"25ccb58f91075df5c5ea9b2d1016b9b2ef209fa6","user":{"login":"houndci","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci","html_url":"https://github.com/houndci","followers_url":"https://api.github.com/users/houndci/followers","following_url":"https://api.github.com/users/houndci/following{/other_user}","gists_url":"https://api.github.com/users/houndci/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci/subscriptions","organizations_url":"https://api.github.com/users/houndci/orgs","repos_url":"https://api.github.com/users/houndci/repos","events_url":"https://api.github.com/users/houndci/events{/privacy}","received_events_url":"https://api.github.com/users/houndci/received_events","type":"User","site_admin":false},"body":"TODO or FIXME Violation: TODOs and FIXMEs should be avoided","created_at":"2015-11-23T04:58:19Z","updated_at":"2015-11-23T04:58:19Z","html_url":"https://github.com/mattrubin/authenticator/pull/50#discussion_r45572746","pull_request_url":"https://api.github.com/repos/mattrubin/authenticator/pulls/50","_links":{"self":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/comments/45572746"},"html":{"href":"https://github.com/mattrubin/authenticator/pull/50#discussion_r45572746"},"pull_request":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/50"}}},"pull_request":{"url":"https://api.github.com/repos/mattrubin/authenticator/pulls/50","id":51488148,"html_url":"https://github.com/mattrubin/authenticator/pull/50","diff_url":"https://github.com/mattrubin/authenticator/pull/50.diff","patch_url":"https://github.com/mattrubin/authenticator/pull/50.patch","issue_url":"https://api.github.com/repos/mattrubin/authenticator/issues/50","number":50,"state":"open","locked":false,"title":"Token Actions","user":{"login":"mattrubin","id":532638,"avatar_url":"https://avatars.githubusercontent.com/u/532638?v=3","gravatar_id":"","url":"https://api.github.com/users/mattrubin","html_url":"https://github.com/mattrubin","followers_url":"https://api.github.com/users/mattrubin/followers","following_url":"https://api.github.com/users/mattrubin/following{/other_user}","gists_url":"https://api.github.com/users/mattrubin/gists{/gist_id}","starred_url":"https://api.github.com/users/mattrubin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattrubin/subscriptions","organizations_url":"https://api.github.com/users/mattrubin/orgs","repos_url":"https://api.github.com/users/mattrubin/repos","events_url":"https://api.github.com/users/mattrubin/events{/privacy}","received_events_url":"https://api.github.com/users/mattrubin/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-11-23T04:58:05Z","updated_at":"2015-11-23T04:58:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a1295e170d0a2d624c6eae3dc91292f240b91b85","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mattrubin/authenticator/pulls/50/commits","review_comments_url":"https://api.github.com/repos/mattrubin/authenticator/pulls/50/comments","review_comment_url":"https://api.github.com/repos/mattrubin/authenticator/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mattrubin/authenticator/issues/50/comments","statuses_url":"https://api.github.com/repos/mattrubin/authenticator/statuses/25ccb58f91075df5c5ea9b2d1016b9b2ef209fa6","head":{"label":"mattrubin:token-actions","ref":"token-actions","sha":"25ccb58f91075df5c5ea9b2d1016b9b2ef209fa6","user":{"login":"mattrubin","id":532638,"avatar_url":"https://avatars.githubusercontent.com/u/532638?v=3","gravatar_id":"","url":"https://api.github.com/users/mattrubin","html_url":"https://github.com/mattrubin","followers_url":"https://api.github.com/users/mattrubin/followers","following_url":"https://api.github.com/users/mattrubin/following{/other_user}","gists_url":"https://api.github.com/users/mattrubin/gists{/gist_id}","starred_url":"https://api.github.com/users/mattrubin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattrubin/subscriptions","organizations_url":"https://api.github.com/users/mattrubin/orgs","repos_url":"https://api.github.com/users/mattrubin/repos","events_url":"https://api.github.com/users/mattrubin/events{/privacy}","received_events_url":"https://api.github.com/users/mattrubin/received_events","type":"User","site_admin":false},"repo":{"id":12443591,"name":"authenticator","full_name":"mattrubin/authenticator","owner":{"login":"mattrubin","id":532638,"avatar_url":"https://avatars.githubusercontent.com/u/532638?v=3","gravatar_id":"","url":"https://api.github.com/users/mattrubin","html_url":"https://github.com/mattrubin","followers_url":"https://api.github.com/users/mattrubin/followers","following_url":"https://api.github.com/users/mattrubin/following{/other_user}","gists_url":"https://api.github.com/users/mattrubin/gists{/gist_id}","starred_url":"https://api.github.com/users/mattrubin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattrubin/subscriptions","organizations_url":"https://api.github.com/users/mattrubin/orgs","repos_url":"https://api.github.com/users/mattrubin/repos","events_url":"https://api.github.com/users/mattrubin/events{/privacy}","received_events_url":"https://api.github.com/users/mattrubin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mattrubin/authenticator","description":"Two-Factor Authentication Client for iOS","fork":false,"url":"https://api.github.com/repos/mattrubin/authenticator","forks_url":"https://api.github.com/repos/mattrubin/authenticator/forks","keys_url":"https://api.github.com/repos/mattrubin/authenticator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mattrubin/authenticator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mattrubin/authenticator/teams","hooks_url":"https://api.github.com/repos/mattrubin/authenticator/hooks","issue_events_url":"https://api.github.com/repos/mattrubin/authenticator/issues/events{/number}","events_url":"https://api.github.com/repos/mattrubin/authenticator/events","assignees_url":"https://api.github.com/repos/mattrubin/authenticator/assignees{/user}","branches_url":"https://api.github.com/repos/mattrubin/authenticator/branches{/branch}","tags_url":"https://api.github.com/repos/mattrubin/authenticator/tags","blobs_url":"https://api.github.com/repos/mattrubin/authenticator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mattrubin/authenticator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mattrubin/authenticator/git/refs{/sha}","trees_url":"https://api.github.com/repos/mattrubin/authenticator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mattrubin/authenticator/statuses/{sha}","languages_url":"https://api.github.com/repos/mattrubin/authenticator/languages","stargazers_url":"https://api.github.com/repos/mattrubin/authenticator/stargazers","contributors_url":"https://api.github.com/repos/mattrubin/authenticator/contributors","subscribers_url":"https://api.github.com/repos/mattrubin/authenticator/subscribers","subscription_url":"https://api.github.com/repos/mattrubin/authenticator/subscription","commits_url":"https://api.github.com/repos/mattrubin/authenticator/commits{/sha}","git_commits_url":"https://api.github.com/repos/mattrubin/authenticator/git/commits{/sha}","comments_url":"https://api.github.com/repos/mattrubin/authenticator/comments{/number}","issue_comment_url":"https://api.github.com/repos/mattrubin/authenticator/issues/comments{/number}","contents_url":"https://api.github.com/repos/mattrubin/authenticator/contents/{+path}","compare_url":"https://api.github.com/repos/mattrubin/authenticator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mattrubin/authenticator/merges","archive_url":"https://api.github.com/repos/mattrubin/authenticator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mattrubin/authenticator/downloads","issues_url":"https://api.github.com/repos/mattrubin/authenticator/issues{/number}","pulls_url":"https://api.github.com/repos/mattrubin/authenticator/pulls{/number}","milestones_url":"https://api.github.com/repos/mattrubin/authenticator/milestones{/number}","notifications_url":"https://api.github.com/repos/mattrubin/authenticator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mattrubin/authenticator/labels{/name}","releases_url":"https://api.github.com/repos/mattrubin/authenticator/releases{/id}","created_at":"2013-08-28T20:15:05Z","updated_at":"2015-11-19T12:35:37Z","pushed_at":"2015-11-23T04:58:05Z","git_url":"git://github.com/mattrubin/authenticator.git","ssh_url":"git@github.com:mattrubin/authenticator.git","clone_url":"https://github.com/mattrubin/authenticator.git","svn_url":"https://github.com/mattrubin/authenticator","homepage":"mattrubin.me/authenticator","size":14734,"stargazers_count":75,"watchers_count":75,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":12,"mirror_url":null,"open_issues_count":8,"forks":12,"open_issues":8,"watchers":75,"default_branch":"master"}},"base":{"label":"mattrubin:master","ref":"master","sha":"7bbbe2cff436ff2a25c28a7e001b1aae62b6a0a5","user":{"login":"mattrubin","id":532638,"avatar_url":"https://avatars.githubusercontent.com/u/532638?v=3","gravatar_id":"","url":"https://api.github.com/users/mattrubin","html_url":"https://github.com/mattrubin","followers_url":"https://api.github.com/users/mattrubin/followers","following_url":"https://api.github.com/users/mattrubin/following{/other_user}","gists_url":"https://api.github.com/users/mattrubin/gists{/gist_id}","starred_url":"https://api.github.com/users/mattrubin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattrubin/subscriptions","organizations_url":"https://api.github.com/users/mattrubin/orgs","repos_url":"https://api.github.com/users/mattrubin/repos","events_url":"https://api.github.com/users/mattrubin/events{/privacy}","received_events_url":"https://api.github.com/users/mattrubin/received_events","type":"User","site_admin":false},"repo":{"id":12443591,"name":"authenticator","full_name":"mattrubin/authenticator","owner":{"login":"mattrubin","id":532638,"avatar_url":"https://avatars.githubusercontent.com/u/532638?v=3","gravatar_id":"","url":"https://api.github.com/users/mattrubin","html_url":"https://github.com/mattrubin","followers_url":"https://api.github.com/users/mattrubin/followers","following_url":"https://api.github.com/users/mattrubin/following{/other_user}","gists_url":"https://api.github.com/users/mattrubin/gists{/gist_id}","starred_url":"https://api.github.com/users/mattrubin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattrubin/subscriptions","organizations_url":"https://api.github.com/users/mattrubin/orgs","repos_url":"https://api.github.com/users/mattrubin/repos","events_url":"https://api.github.com/users/mattrubin/events{/privacy}","received_events_url":"https://api.github.com/users/mattrubin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mattrubin/authenticator","description":"Two-Factor Authentication Client for iOS","fork":false,"url":"https://api.github.com/repos/mattrubin/authenticator","forks_url":"https://api.github.com/repos/mattrubin/authenticator/forks","keys_url":"https://api.github.com/repos/mattrubin/authenticator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mattrubin/authenticator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mattrubin/authenticator/teams","hooks_url":"https://api.github.com/repos/mattrubin/authenticator/hooks","issue_events_url":"https://api.github.com/repos/mattrubin/authenticator/issues/events{/number}","events_url":"https://api.github.com/repos/mattrubin/authenticator/events","assignees_url":"https://api.github.com/repos/mattrubin/authenticator/assignees{/user}","branches_url":"https://api.github.com/repos/mattrubin/authenticator/branches{/branch}","tags_url":"https://api.github.com/repos/mattrubin/authenticator/tags","blobs_url":"https://api.github.com/repos/mattrubin/authenticator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mattrubin/authenticator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mattrubin/authenticator/git/refs{/sha}","trees_url":"https://api.github.com/repos/mattrubin/authenticator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mattrubin/authenticator/statuses/{sha}","languages_url":"https://api.github.com/repos/mattrubin/authenticator/languages","stargazers_url":"https://api.github.com/repos/mattrubin/authenticator/stargazers","contributors_url":"https://api.github.com/repos/mattrubin/authenticator/contributors","subscribers_url":"https://api.github.com/repos/mattrubin/authenticator/subscribers","subscription_url":"https://api.github.com/repos/mattrubin/authenticator/subscription","commits_url":"https://api.github.com/repos/mattrubin/authenticator/commits{/sha}","git_commits_url":"https://api.github.com/repos/mattrubin/authenticator/git/commits{/sha}","comments_url":"https://api.github.com/repos/mattrubin/authenticator/comments{/number}","issue_comment_url":"https://api.github.com/repos/mattrubin/authenticator/issues/comments{/number}","contents_url":"https://api.github.com/repos/mattrubin/authenticator/contents/{+path}","compare_url":"https://api.github.com/repos/mattrubin/authenticator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mattrubin/authenticator/merges","archive_url":"https://api.github.com/repos/mattrubin/authenticator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mattrubin/authenticator/downloads","issues_url":"https://api.github.com/repos/mattrubin/authenticator/issues{/number}","pulls_url":"https://api.github.com/repos/mattrubin/authenticator/pulls{/number}","milestones_url":"https://api.github.com/repos/mattrubin/authenticator/milestones{/number}","notifications_url":"https://api.github.com/repos/mattrubin/authenticator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mattrubin/authenticator/labels{/name}","releases_url":"https://api.github.com/repos/mattrubin/authenticator/releases{/id}","created_at":"2013-08-28T20:15:05Z","updated_at":"2015-11-19T12:35:37Z","pushed_at":"2015-11-23T04:58:05Z","git_url":"git://github.com/mattrubin/authenticator.git","ssh_url":"git@github.com:mattrubin/authenticator.git","clone_url":"https://github.com/mattrubin/authenticator.git","svn_url":"https://github.com/mattrubin/authenticator","homepage":"mattrubin.me/authenticator","size":14734,"stargazers_count":75,"watchers_count":75,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":12,"mirror_url":null,"open_issues_count":8,"forks":12,"open_issues":8,"watchers":75,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/50"},"html":{"href":"https://github.com/mattrubin/authenticator/pull/50"},"issue":{"href":"https://api.github.com/repos/mattrubin/authenticator/issues/50"},"comments":{"href":"https://api.github.com/repos/mattrubin/authenticator/issues/50/comments"},"review_comments":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/50/comments"},"review_comment":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mattrubin/authenticator/pulls/50/commits"},"statuses":{"href":"https://api.github.com/repos/mattrubin/authenticator/statuses/25ccb58f91075df5c5ea9b2d1016b9b2ef209fa6"}}}}