diff --git a/src/Model/Item.php b/src/Model/Item.php index 6b48acf4c..081babd99 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -2946,39 +2946,6 @@ class Item return false; } - switch ($verb) { - case 'like': - case 'unlike': - $activity = Activity::LIKE; - break; - case 'dislike': - case 'undislike': - $activity = Activity::DISLIKE; - break; - case 'attendyes': - case 'unattendyes': - $activity = Activity::ATTEND; - break; - case 'attendno': - case 'unattendno': - $activity = Activity::ATTENDNO; - break; - case 'attendmaybe': - case 'unattendmaybe': - $activity = Activity::ATTENDMAYBE; - break; - case 'follow': - case 'unfollow': - $activity = Activity::FOLLOW; - break; - default: - Logger::log('like: unknown verb ' . $verb . ' for item ' . $item_id); - return false; - } - - // Enable activity toggling instead of on/off - $event_verb_flag = $activity === Activity::ATTEND || $activity === Activity::ATTENDNO || $activity === Activity::ATTENDMAYBE; - Logger::log('like: verb ' . $verb . ' item ' . $item_id); $item = self::selectFirst(self::ITEM_FIELDLIST, ['`id` = ? OR `uri` = ?', $item_id, $item_id]); @@ -3027,9 +2994,43 @@ class Item } } + switch ($verb) { + case 'like': + case 'unlike': + $activity = Activity::LIKE; + break; + case 'dislike': + case 'undislike': + $activity = Activity::DISLIKE; + break; + case 'attendyes': + case 'unattendyes': + $activity = Activity::ATTEND; + break; + case 'attendno': + case 'unattendno': + $activity = Activity::ATTENDNO; + break; + case 'attendmaybe': + case 'unattendmaybe': + $activity = Activity::ATTENDMAYBE; + break; + case 'follow': + case 'unfollow': + $activity = Activity::FOLLOW; + break; + default: + Logger::log('like: unknown verb ' . $verb . ' for item ' . $item_id); + return false; + } + + $mode = Strings::startsWith($verb, 'un') ? 'delete' : 'create'; + + // Enable activity toggling instead of on/off + $event_verb_flag = $activity === Activity::ATTEND || $activity === Activity::ATTENDNO || $activity === Activity::ATTENDMAYBE; + // Look for an existing verb row - // event participation are essentially radio toggles. If you make a subsequent choice, - // we need to eradicate your first choice. + // Event participation activities are mutually exclusive, only one of them can exist at all times. if ($event_verb_flag) { $verbs = [Activity::ATTEND, Activity::ATTENDNO, Activity::ATTENDMAYBE]; @@ -3044,20 +3045,43 @@ class Item $condition = ['vid' => $vids, 'deleted' => false, 'gravity' => GRAVITY_ACTIVITY, 'author-id' => $author_id, 'uid' => $item['uid'], 'thr-parent' => $item_uri]; - $like_item = self::selectFirst(['id', 'guid', 'verb'], $condition); - // If it exists, mark it as deleted if (DBA::isResult($like_item)) { - self::markForDeletionById($like_item['id']); + /** + * Truth table for existing activities + * + * | Inputs || Outputs | + * |----------------------------||-------------------| + * | Mode | Event | Same verb || Delete? | Return? | + * |--------|-------|-----------||---------|---------| + * | create | Yes | Yes || No | Yes | + * | create | Yes | No || Yes | No | + * | create | No | Yes || No | Yes | + * | create | No | No || N/A† | + * | delete | Yes | Yes || Yes | N/A‡ | + * | delete | Yes | No || No | N/A‡ | + * | delete | No | Yes || Yes | N/A‡ | + * | delete | No | No || N/A† | + * |--------|-------|-----------||---------|---------| + * | A | B | C || A xor C | !B or C | + * + * † Can't happen: It's impossible to find an existing non-event activity without + * the same verb because we are only looking for this single verb. + * + * ‡ The "mode = delete" is returning early whether an existing activity was found or not. + */ + if ($mode == 'create' xor $like_item['verb'] == $activity) { + self::markForDeletionById($like_item['id']); + } if (!$event_verb_flag || $like_item['verb'] == $activity) { return true; } } - // Verb is "un-something", just trying to delete existing entries - if (strpos($verb, 'un') === 0) { + // No need to go further if we aren't creating anything + if ($mode == 'delete') { return true; } diff --git a/view/js/main.js b/view/js/main.js index af2f8522c..60337918b 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -649,9 +649,15 @@ function imgdull(node) { // trickery. This still could cause confusion if the "like" ajax call // is delayed and NavUpdate runs before it completes. -function dolike(ident,verb) { +/** + * @param {int} ident The id of the relevant item + * @param {string} verb The verb of the action + * @param {boolean} un Whether to perform an activity removal instead of creation + */ +function dolike(ident, verb, un) { unpause(); $('#like-rotator-' + ident.toString()).show(); + verb = un ? 'un' + verb : verb; $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate); liking = 1; force_update = true; diff --git a/view/templates/wall_thread.tpl b/view/templates/wall_thread.tpl index 7b205504d..0d8c896e1 100644 --- a/view/templates/wall_thread.tpl +++ b/view/templates/wall_thread.tpl @@ -77,8 +77,8 @@
{{if $item.vote}}
- - {{if $item.vote.dislike}}{{/if}} + + {{if $item.vote.dislike}}{{/if}} {{if $item.vote.share}}{{/if}}
@@ -107,9 +107,9 @@ {{/if}} {{if $item.isevent }}
- - - + + +
{{/if}}
diff --git a/view/theme/frio/js/theme.js b/view/theme/frio/js/theme.js index 3a3f02c5e..6b85e610e 100644 --- a/view/theme/frio/js/theme.js +++ b/view/theme/frio/js/theme.js @@ -721,22 +721,17 @@ function htmlToText(htmlString) { * Sends a /like API call and updates the display of the relevant action button * before the update reloads the item. * - * @param {string} ident The id of the relevant item - * @param {string} verb The verb of the action - * @returns {undefined} + * @param {int} ident The id of the relevant item + * @param {string} verb The verb of the action + * @param {boolean} un Whether to perform an activity removal instead of creation */ -function doLikeAction(ident, verb) { - unpause(); - +function doLikeAction(ident, verb, un) { if (verb.indexOf('attend') === 0) { $('.item-' + ident + ' .button-event:not(#' + verb + '-' + ident + ')').removeClass('active'); } $('#' + verb + '-' + ident).toggleClass('active'); - $('#like-rotator-' + ident.toString()).show(); - $.get('like/' + ident.toString() + '?verb=' + verb, NavUpdate ); - liking = 1; - force_update = true; - update_item = ident.toString(); + + dolike(ident, verb, un); } // Decodes a hexadecimally encoded binary string diff --git a/view/theme/frio/templates/search_item.tpl b/view/theme/frio/templates/search_item.tpl index 1cbd8451d..ce5497dda 100644 --- a/view/theme/frio/templates/search_item.tpl +++ b/view/theme/frio/templates/search_item.tpl @@ -144,14 +144,14 @@ {{* Buttons for like and dislike *}} {{if $item.vote}} {{if $item.vote.like}} - + {{/if}} {{if $item.vote.like AND $item.vote.dislike}} {{/if}} {{if $item.vote.dislike}} - + {{/if}} {{if ($item.vote.like OR $item.vote.dislike) AND $item.comment}} @@ -249,9 +249,9 @@ {{* Event attendance buttons *}} {{if $item.isevent}} - - - + + + {{/if}} diff --git a/view/theme/frio/templates/wall_thread.tpl b/view/theme/frio/templates/wall_thread.tpl index a5a785af7..c15b110ec 100644 --- a/view/theme/frio/templates/wall_thread.tpl +++ b/view/theme/frio/templates/wall_thread.tpl @@ -282,13 +282,13 @@ as the value of $top_child_total (this is done at the end of this file) {{* Buttons for like and dislike *}} {{if $item.vote}} {{if $item.vote.like}} - + {{/if}} {{if $item.vote.like AND $item.vote.dislike}} {{/if}} {{if $item.vote.dislike}} - + {{/if}} {{if ($item.vote.like OR $item.vote.dislike) AND $item.comment}} @@ -390,9 +390,9 @@ as the value of $top_child_total (this is done at the end of this file) {{* Event attendance buttons *}} {{if $item.isevent}} - - - + + + {{/if}} @@ -409,10 +409,10 @@ as the value of $top_child_total (this is done at the end of this file) {{if $item.vote}}
{{if $item.vote.like}} - + {{/if}} {{if $item.vote.dislike}} - + {{/if}}
{{/if}} @@ -441,9 +441,9 @@ as the value of $top_child_total (this is done at the end of this file) {{* Event attendance buttons *}} {{if $item.isevent}}
- - - + + +
{{/if}} diff --git a/view/theme/quattro/templates/photo_item.tpl b/view/theme/quattro/templates/photo_item.tpl index b196824c0..e14caa542 100644 --- a/view/theme/quattro/templates/photo_item.tpl +++ b/view/theme/quattro/templates/photo_item.tpl @@ -39,8 +39,8 @@ {{/if}} {{if $vote}} - {{$vote.like.1}} - {{$vote.dislike.1}} + {{$vote.like.1}} + {{$vote.dislike.1}} {{/if}} {{if $vote.share}} diff --git a/view/theme/quattro/templates/search_item.tpl b/view/theme/quattro/templates/search_item.tpl index 38ac6cf63..0e4aaaf8f 100644 --- a/view/theme/quattro/templates/search_item.tpl +++ b/view/theme/quattro/templates/search_item.tpl @@ -54,10 +54,10 @@ {{/if}} {{if $item.vote.like}} - {{$item.vote.like.1}} + {{$item.vote.like.1}} {{/if}} {{if $item.vote.dislike}} - {{$item.vote.dislike.1}} + {{$item.vote.dislike.1}} {{/if}} {{if $item.vote.share}} diff --git a/view/theme/quattro/templates/wall_thread.tpl b/view/theme/quattro/templates/wall_thread.tpl index 10f8fe998..e6d8b9754 100644 --- a/view/theme/quattro/templates/wall_thread.tpl +++ b/view/theme/quattro/templates/wall_thread.tpl @@ -118,9 +118,9 @@ {{/if}} {{if $item.vote}} - {{$item.vote.like.1}} + {{$item.vote.like.1}} {{if $item.vote.dislike}} - {{$item.vote.dislike.1}} + {{$item.vote.dislike.1}} {{/if}} {{if $item.vote.share}} {{$item.vote.share.1}} @@ -129,9 +129,9 @@ {{if $item.isevent}}
{{/if}} diff --git a/view/theme/smoothly/templates/wall_thread.tpl b/view/theme/smoothly/templates/wall_thread.tpl index b372fbefb..85d480c31 100644 --- a/view/theme/smoothly/templates/wall_thread.tpl +++ b/view/theme/smoothly/templates/wall_thread.tpl @@ -91,9 +91,9 @@ {{if $item.vote}}