{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-app-android/pulls/comments/74490986","id":74490986,"diff_hunk":"@@ -0,0 +1,474 @@\n+package org.edx.mobile.third_party.versioning;\n+\n+/*\n+ * This class has been copied from the Maven Artifact project.\n+ * The main() method has been removed from it, as that was\n+ * useful only for the standalone project.\n+ *\n+ * Licensed to the Apache Software Foundation (ASF) under one\n+ * or more contributor license agreements.  See the NOTICE file\n+ * distributed with this work for additional information\n+ * regarding copyright ownership.  The ASF licenses this file\n+ * to you under the Apache License, Version 2.0 (the\n+ * \"License\"); you may not use this file except in compliance\n+ * with the License.  You may obtain a copy of the License at\n+ *\n+ *  http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing,\n+ * software distributed under the License is distributed on an\n+ * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n+ * KIND, either express or implied.  See the License for the\n+ * specific language governing permissions and limitations\n+ * under the License.\n+ */\n+\n+import java.math.BigInteger;\n+import java.util.ArrayList;\n+import java.util.Arrays;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Locale;\n+import java.util.Properties;\n+import java.util.Stack;\n+\n+/**\n+ * Generic implementation of version comparison.\n+ *\n+ * <p>Features:\n+ * <ul>\n+ * <li>mixing of '<code>-</code>' (dash) and '<code>.</code>' (dot) separators,</li>\n+ * <li>transition between characters and digits also constitutes a separator:\n+ *     <code>1.0alpha1 =&gt; [1, 0, alpha, 1]</code></li>\n+ * <li>unlimited number of version components,</li>\n+ * <li>version components in the text can be digits or strings,</li>\n+ * <li>strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering.\n+ *     Well-known qualifiers (case insensitive) are:<ul>\n+ *     <li><code>alpha</code> or <code>a</code></li>\n+ *     <li><code>beta</code> or <code>b</code></li>\n+ *     <li><code>milestone</code> or <code>m</code></li>\n+ *     <li><code>rc</code> or <code>cr</code></li>\n+ *     <li><code>snapshot</code></li>\n+ *     <li><code>(the empty string)</code> or <code>ga</code> or <code>final</code></li>\n+ *     <li><code>sp</code></li>\n+ *     </ul>\n+ *     Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),\n+ *   </li>\n+ * <li>a dash usually precedes a qualifier, and is always less important than something preceded with a dot.</li>\n+ * </ul></p>\n+ *\n+ * @see <a href=\"https://cwiki.apache.org/confluence/display/MAVENOLD/Versioning\">\"Versioning\" on Maven Wiki</a>\n+ * @author <a href=\"mailto:kenney@apache.org\">Kenney Westerhof</a>\n+ * @author <a href=\"mailto:hboutemy@apache.org\">Hervé Boutemy</a>\n+ */\n+public class ComparableVersion","path":"VideoLocker/src/main/java/org/edx/mobile/third_party/versioning/ComparableVersion.java","position":63,"original_position":64,"commit_id":"a2cf2d6cf9cc69c33c7443aabd07c57fecf1f238","original_commit_id":"e1d944e9560d70b05b4364db1b8d2ec211cc23ba","user":{"login":"bguertin","id":1685613,"avatar_url":"https://avatars.githubusercontent.com/u/1685613?v=3","gravatar_id":"","url":"https://api.github.com/users/bguertin","html_url":"https://github.com/bguertin","followers_url":"https://api.github.com/users/bguertin/followers","following_url":"https://api.github.com/users/bguertin/following{/other_user}","gists_url":"https://api.github.com/users/bguertin/gists{/gist_id}","starred_url":"https://api.github.com/users/bguertin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bguertin/subscriptions","organizations_url":"https://api.github.com/users/bguertin/orgs","repos_url":"https://api.github.com/users/bguertin/repos","events_url":"https://api.github.com/users/bguertin/events{/privacy}","received_events_url":"https://api.github.com/users/bguertin/received_events","type":"User","site_admin":false},"body":"So, the version format is described precisely here: https://github.com/edx/edx-platform/blob/5f572dfc674ae576ee72f4308d18b470e7498891/lms/djangoapps/mobile_api/models.py#L42\r\n\r\nIt says: `Version should be in the format X.X.X.Y where X is a number and Y is alphanumeric`\r\n\r\nI added a test for the alphanumberic case (which differes from SemVer) to this Version class: https://gist.github.com/bguertin/40d1b00e11adeaa1357e4ab747882d30","created_at":"2016-08-11T19:52:09Z","updated_at":"2016-08-11T19:52:09Z","html_url":"https://github.com/edx/edx-app-android/pull/748#discussion_r74490986","pull_request_url":"https://api.github.com/repos/edx/edx-app-android/pulls/748","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/comments/74490986"},"html":{"href":"https://github.com/edx/edx-app-android/pull/748#discussion_r74490986"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/748"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-app-android/pulls/748","id":73916386,"html_url":"https://github.com/edx/edx-app-android/pull/748","diff_url":"https://github.com/edx/edx-app-android/pull/748.diff","patch_url":"https://github.com/edx/edx-app-android/pull/748.patch","issue_url":"https://api.github.com/repos/edx/edx-app-android/issues/748","number":748,"state":"open","locked":false,"title":"Implement Snackbar notifications for new releases","user":{"login":"1zaman","id":4244109,"avatar_url":"https://avatars.githubusercontent.com/u/4244109?v=3","gravatar_id":"","url":"https://api.github.com/users/1zaman","html_url":"https://github.com/1zaman","followers_url":"https://api.github.com/users/1zaman/followers","following_url":"https://api.github.com/users/1zaman/following{/other_user}","gists_url":"https://api.github.com/users/1zaman/gists{/gist_id}","starred_url":"https://api.github.com/users/1zaman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/1zaman/subscriptions","organizations_url":"https://api.github.com/users/1zaman/orgs","repos_url":"https://api.github.com/users/1zaman/repos","events_url":"https://api.github.com/users/1zaman/events{/privacy}","received_events_url":"https://api.github.com/users/1zaman/received_events","type":"User","site_admin":false},"body":"### Description\r\n\r\n[MA-1995][]\r\n\r\nAn OkHttp interceptor has been added to capture the headers notifying of new versions of the app that have been release on the app stores. These are broadcasted over the event bus and displayed on `MyCoursesListActivity` (the main dashboard Activity) [in the form of Snackbars][Version Upgrade Alerts], that will persist until the user swipes them away. The maximum limit for the number of lines in the Snackbar messages has also been raised from 2 to 10, to stop the error messages from getting truncated.\r\n\r\nThe Activity is treated as a session, with notifications not being repeated in a single session, but reset after the session is closed. This [design][notifications session proposal] is so that the notifications are always provided directly by the server, instead of being persisted on the local device. This will prevent wrongly sent headers to permanently change the app state to an incorrect one.\r\n\r\nThere are [three different notifications][Version-based App Upgrade] in descending order of priority. New notifications will only be shown if they have a higher priority than any other one that has been shown in the current session.\r\n\r\n1. Unsupported app version notifications. This is when we get a 426 (upgrade required) error as a response. This means that the API we're calling has been removed, and will no longer deliver anything.\r\n\r\n2. Deprecation notification. This is when we get notified of a new version of the app, along with a deadline after which the current version won't have it's API calls supported any longer. These are prioritized according to the closeness of their deadlines.\r\n\r\n3. New release notification. This is when we get notified of a new version of the app, without any deadline for support of the current version.  These are prioritized according to the largest new version number.\r\n\r\n~~Apache Commons Lang 3 has been added as a new dependency, since it's `FastDateFormat` is a very useful improvement over the built-in `SimpleDateFormat`, and provides much better support for ISO 8601, which seems to be the standard used by the dates sent by the server. Specifically, the last supported date header is being sent with UTC offsets, which is part of the ISO 8601 standard, and also supported by `FastDateFormat`. All `SimpleDateFormat` usages should be replaced with `FastDateFormat` in the future.~~\r\n\r\nIn addition to this, some utility classes have been copied over from the Maven Artifact project in order to compare the version numbers, since we seem to following the same general versioning scheme as Maven artifacts.\r\n\r\n### Screenshots\r\n\r\nUnsupported | Deprecated | Outdated\r\n------------|------------|---------\r\n![version_unsupported][] | ![version_deprecated][] | ![version_outdated][]\r\n\r\n### Notes\r\n - This can be tested with the `temp-lahore` sandbox. Configuration can be done at https://temp-lahore.sandbox.edx.org/admin/mobile_api/appversionconfig/2.\r\n\r\n### Testing\r\n- [ ] Unit, integration, acceptance tests as appropriate\r\n\r\n### Reviewers\r\nIf you've been tagged for review, please check your corresponding box once you've given the :+1:.\r\n- [x] Code review: @miankhalid\r\n- [x] Code review: @BenjiLee\r\n- [ ] Code review: @bguertin\r\n- [x] Code review: @mdinino\r\n- [x] UI strings/error msgs review: @catong\r\n- [x] UX review: @lizcohen\r\n\r\n[MA-1995]: https://openedx.atlassian.net/browse/MA-1995\r\n\r\n[Version Upgrade Alerts]: https://openedx.atlassian.net/wiki/display/MA/Version+Upgrade+Alerts\r\n[Version-based App Upgrade]: https://openedx.atlassian.net/wiki/display/MA/Version-based+App+Upgrade\r\n[notifications session proposal]: https://openedx.atlassian.net/wiki/display/MA/API+Unavailable+UX?focusedCommentId=85590017#comment-85590017\r\n\r\n[version_unsupported]: https://cloud.githubusercontent.com/assets/4244109/16081619/b9d538aa-3327-11e6-8097-4f5ab55bf17c.png\r\n[version_deprecated]: https://cloud.githubusercontent.com/assets/4244109/16081681/efc88f02-3327-11e6-9335-9e2c7e7c3be2.png\r\n[version_outdated]: https://cloud.githubusercontent.com/assets/4244109/16081747/40a7aa84-3328-11e6-9fda-a70445f8086a.png","created_at":"2016-06-15T13:58:58Z","updated_at":"2016-08-11T19:52:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"279d328c8541f19bbc30059c71f84c9e6bc5747f","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-app-android/pulls/748/commits","review_comments_url":"https://api.github.com/repos/edx/edx-app-android/pulls/748/comments","review_comment_url":"https://api.github.com/repos/edx/edx-app-android/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/edx-app-android/issues/748/comments","statuses_url":"https://api.github.com/repos/edx/edx-app-android/statuses/a2cf2d6cf9cc69c33c7443aabd07c57fecf1f238","head":{"label":"edx:MA-1995","ref":"MA-1995","sha":"a2cf2d6cf9cc69c33c7443aabd07c57fecf1f238","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":29251742,"name":"edx-app-android","full_name":"edx/edx-app-android","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-app-android","description":"","fork":false,"url":"https://api.github.com/repos/edx/edx-app-android","forks_url":"https://api.github.com/repos/edx/edx-app-android/forks","keys_url":"https://api.github.com/repos/edx/edx-app-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-app-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-app-android/teams","hooks_url":"https://api.github.com/repos/edx/edx-app-android/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-app-android/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-app-android/events","assignees_url":"https://api.github.com/repos/edx/edx-app-android/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-app-android/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-app-android/tags","blobs_url":"https://api.github.com/repos/edx/edx-app-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-app-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-app-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-app-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-app-android/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-app-android/languages","stargazers_url":"https://api.github.com/repos/edx/edx-app-android/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-app-android/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-app-android/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-app-android/subscription","commits_url":"https://api.github.com/repos/edx/edx-app-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-app-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-app-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-app-android/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-app-android/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-app-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-app-android/merges","archive_url":"https://api.github.com/repos/edx/edx-app-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-app-android/downloads","issues_url":"https://api.github.com/repos/edx/edx-app-android/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-app-android/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-app-android/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-app-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-app-android/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-app-android/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-app-android/deployments","created_at":"2015-01-14T15:49:47Z","updated_at":"2016-08-11T11:13:31Z","pushed_at":"2016-08-11T17:35:50Z","git_url":"git://github.com/edx/edx-app-android.git","ssh_url":"git@github.com:edx/edx-app-android.git","clone_url":"https://github.com/edx/edx-app-android.git","svn_url":"https://github.com/edx/edx-app-android","homepage":null,"size":23646,"stargazers_count":88,"watchers_count":88,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":94,"mirror_url":null,"open_issues_count":14,"forks":94,"open_issues":14,"watchers":88,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"b6d0b3bf560743a3aa805b9c071d905af6cad0f6","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":29251742,"name":"edx-app-android","full_name":"edx/edx-app-android","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-app-android","description":"","fork":false,"url":"https://api.github.com/repos/edx/edx-app-android","forks_url":"https://api.github.com/repos/edx/edx-app-android/forks","keys_url":"https://api.github.com/repos/edx/edx-app-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-app-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-app-android/teams","hooks_url":"https://api.github.com/repos/edx/edx-app-android/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-app-android/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-app-android/events","assignees_url":"https://api.github.com/repos/edx/edx-app-android/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-app-android/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-app-android/tags","blobs_url":"https://api.github.com/repos/edx/edx-app-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-app-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-app-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-app-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-app-android/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-app-android/languages","stargazers_url":"https://api.github.com/repos/edx/edx-app-android/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-app-android/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-app-android/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-app-android/subscription","commits_url":"https://api.github.com/repos/edx/edx-app-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-app-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-app-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-app-android/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/edx-app-android/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-app-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-app-android/merges","archive_url":"https://api.github.com/repos/edx/edx-app-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-app-android/downloads","issues_url":"https://api.github.com/repos/edx/edx-app-android/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-app-android/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-app-android/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-app-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-app-android/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-app-android/releases{/id}","deployments_url":"https://api.github.com/repos/edx/edx-app-android/deployments","created_at":"2015-01-14T15:49:47Z","updated_at":"2016-08-11T11:13:31Z","pushed_at":"2016-08-11T17:35:50Z","git_url":"git://github.com/edx/edx-app-android.git","ssh_url":"git@github.com:edx/edx-app-android.git","clone_url":"https://github.com/edx/edx-app-android.git","svn_url":"https://github.com/edx/edx-app-android","homepage":null,"size":23646,"stargazers_count":88,"watchers_count":88,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":94,"mirror_url":null,"open_issues_count":14,"forks":94,"open_issues":14,"watchers":88,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/748"},"html":{"href":"https://github.com/edx/edx-app-android/pull/748"},"issue":{"href":"https://api.github.com/repos/edx/edx-app-android/issues/748"},"comments":{"href":"https://api.github.com/repos/edx/edx-app-android/issues/748/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/748/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-app-android/pulls/748/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-app-android/statuses/a2cf2d6cf9cc69c33c7443aabd07c57fecf1f238"}}}}
{"actor":{"display_login":"bguertin"}}