summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Interfaces/Object/LikeInterface.php4
-rw-r--r--lib/Model/ActivityPub/ACore.php3
-rw-r--r--lib/Service/ActionService.php10
-rw-r--r--lib/Service/LikeService.php4
-rw-r--r--src/components/Composer/Composer.vue45
-rw-r--r--src/views/Profile.vue13
6 files changed, 56 insertions, 23 deletions
diff --git a/lib/Interfaces/Object/LikeInterface.php b/lib/Interfaces/Object/LikeInterface.php
index da08ab8e..27039305 100644
--- a/lib/Interfaces/Object/LikeInterface.php
+++ b/lib/Interfaces/Object/LikeInterface.php
@@ -109,7 +109,9 @@ class LikeInterface extends AbstractActivityPubInterface implements IActivityPub
public function getItem(ACore $item): ACore {
try {
return $this->actionsRequest->getAction(
- $item->getActorId(), $item->getObjectId(), Like::TYPE
+ $item->getActorId(),
+ $item->getObjectId(),
+ Like::TYPE
);
} catch (ActionDoesNotExistException $e) {
}
diff --git a/lib/Model/ActivityPub/ACore.php b/lib/Model/ActivityPub/ACore.php
index a30d2197..7b950a69 100644
--- a/lib/Model/ActivityPub/ACore.php
+++ b/lib/Model/ActivityPub/ACore.php
@@ -37,11 +37,12 @@ use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\LinkedDataSignature;
+use OCA\Social\Tools\IQueryRow;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Tools\Traits\TPathTools;
use OCA\Social\Tools\Traits\TStringTools;
-class ACore extends Item implements JsonSerializable {
+class ACore extends Item implements JsonSerializable, IQueryRow {
use TArrayTools;
use TStringTools;
use TPathTools;
diff --git a/lib/Service/ActionService.php b/lib/Service/ActionService.php
index b318c795..08c81aa1 100644
--- a/lib/Service/ActionService.php
+++ b/lib/Service/ActionService.php
@@ -40,6 +40,7 @@ class ActionService {
private StreamService $streamService;
private BoostService $boostService;
+ private LikeService $likeService;
private StreamActionService $streamActionService;
private const TRANSLATE = 'translate';
@@ -71,10 +72,12 @@ class ActionService {
public function __construct(
StreamService $streamService,
BoostService $boostService,
+ LikeService $likeService,
StreamActionService $streamActionService
) {
$this->streamService = $streamService;
$this->boostService = $boostService;
+ $this->likeService = $likeService;
$this->streamActionService = $streamActionService;
}
@@ -134,8 +137,11 @@ class ActionService {
}
private function favourite(Person $actor, string $postId, bool $enabled = true): void {
- $this->boostService->delete($actor, $postId);
-// $this->streamActionService->setActionBool($actor->getId(), $postId, StreamAction::LIKED, $enabled);
+ if ($enabled) {
+ $this->likeService->create($actor, $postId);
+ } else {
+ $this->likeService->delete($actor, $postId);
+ }
}
private function reblog(Person $actor, string $postId, bool $enabled = true): void {
diff --git a/lib/Service/LikeService.php b/lib/Service/LikeService.php
index b70e4bde..b8f6ab34 100644
--- a/lib/Service/LikeService.php
+++ b/lib/Service/LikeService.php
@@ -108,7 +108,7 @@ class LikeService {
* @throws SocialAppConfigException
* @throws Exception
*/
- public function create(Person $actor, string $postId, &$token = ''): ACore {
+ public function create(Person $actor, string $postId, string &$token = ''): ACore {
/** @var Like $like */
$like = AP::$activityPub->getItemFromType(Like::TYPE);
$like->setId($actor->getId() . '#like/' . $this->uuid(8));
@@ -160,7 +160,7 @@ class LikeService {
* @throws SocialAppConfigException
* @throws StreamNotFoundException
*/
- public function delete(Person $actor, string $postId, &$token = ''): ACore {
+ public function delete(Person $actor, string $postId, string &$token = ''): ACore {
$undo = new Undo();
$undo->setActor($actor);
diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue
index 055f2d8c..a1ee329f 100644
--- a/src/components/Composer/Composer.vue
+++ b/src/components/Composer/Composer.vue
@@ -109,17 +109,6 @@
<VisibilitySelect :visibility.sync="visibility" />
<div class="emptySpace" />
<SubmitStatusButton :visibility="visibility" :disabled="!canPost || loading" @click="createPost" />
-
- <!-- <NcButton :value="currentVisibilityPostLabel"
- :disabled="!canPost"
- native-type="submit"
- type="primary"
- @click.prevent="createPost">
- <template #icon>
- <Send title="" :size="22" decorative />
- </template>
- {{ postTo }}
- </NcButton> -->
</div>
</form>
</div>
@@ -172,10 +161,21 @@ export default {
FocusOnCreate,
},
mixins: [CurrentUserMixin],
+ props: {
+ /** @type {import('vue').PropType<import('../types/Mastodon.js').Status|null>} */
+ initialMention: {
+ type: Object,
+ default: null,
+ },
+ defaultVisibility: {
+ type: String,
+ default: localStorage.getItem('social.lastPostType') || 'followers',
+ },
+ },
data() {
return {
statusContent: '',
- visibility: localStorage.getItem('social.lastPostType') || 'followers',
+ visibility: this.defaultVisibility,
loading: false,
/** @type {Object<string, LocalAttachment>} */
attachments: {},
@@ -197,8 +197,13 @@ export default {
+ '</div>'
},
selectTemplate(item) {
- return '<span class="mention" contenteditable="false">'
- + '<a href="' + item.original.url + '" target="_blank"><img src="' + item.original.avatar + '" />@' + item.original.value + '</a></span>'
+ return `
+ <span class="mention" contenteditable="false">
+ <a href="${item.original.url}" target="_blank">
+ <img src="${item.original.avatar}"/>
+ @${item.original.value}
+ </a>
+ </span>`
},
values: debounce(async (text, populate) => {
if (text.length < 1) {
@@ -281,6 +286,17 @@ export default {
this.replyTo = data
this.visibility = data.visibility
})
+
+ if (this.initialMention !== null) {
+ this.$refs.composerInput.innerHTML = `
+ <span class="mention" contenteditable="false">
+ <a href="${this.initialMention.url}" target="_blank">
+ <img src="${!this.initialMention.acct.includes('@') ? generateUrl(`/avatar/${this.initialMention.username}/32`) : generateUrl(`apps/social/api/v1/global/actor/avatar?id=${this.initialMention.acct}`)}"/>
+ @${this.initialMention.acct}
+ </a>
+ </span>&nbsp;`
+ this.updateStatusContent()
+ }
},
methods: {
updateStatusContent() {
@@ -402,7 +418,6 @@ export default {
},
},
}
-
</script>
<style scoped lang="scss">
diff --git a/src/views/Profile.vue b/src/views/Profile.vue
index fd3a162e..f0fae400 100644
--- a/src/views/Profile.vue
+++ b/src/views/Profile.vue
@@ -23,6 +23,9 @@
<template>
<div :class="{'icon-loading': !accountLoaded}" class="social__wrapper">
<ProfileInfo v-if="accountLoaded && accountInfo" :uid="uid" />
+
+ <Composer v-if="accountInfo" :initial-mention="accountInfo.acct === currentAccount.acct ? null : accountInfo" default-visibility="direct" />
+
<!-- TODO: we have no details, timeline and follower list for non-local accounts for now -->
<router-view v-if="accountLoaded && accountInfo && isLocal" name="details" />
<NcEmptyContent v-if="accountLoaded && !accountInfo"
@@ -38,17 +41,19 @@
</template>
<script>
-import ProfileInfo from './../components/ProfileInfo.vue'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
+import { generateFilePath } from '@nextcloud/router'
+import ProfileInfo from './../components/ProfileInfo.vue'
+import Composer from './../components/Composer/Composer.vue'
import accountMixins from '../mixins/accountMixins.js'
import serverData from '../mixins/serverData.js'
-import { generateFilePath } from '@nextcloud/router'
export default {
name: 'Profile',
components: {
NcEmptyContent,
ProfileInfo,
+ Composer,
},
mixins: [
accountMixins,
@@ -70,6 +75,10 @@ export default {
emptyContentImage() {
return generateFilePath('social', 'img', 'undraw/profile.svg')
},
+ /** @return {import('../types/Mastodon.js').Account} */
+ currentAccount() {
+ return this.$store.getters.currentAccount
+ },
},
// Start fetching account information before mounting the component
async beforeMount() {