1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15- import { Component , Input , OnInit } from '@angular/core' ;
16- import { CoreSites , CoreSitesReadingStrategy } from '@services/sites' ;
15+ import { Component , computed , effect , input , linkedSignal , signal , untracked } from '@angular/core' ;
16+ import { CoreSitesReadingStrategy } from '@services/sites' ;
1717import { CoreNetwork } from '@services/network' ;
1818import { AddonModForum , AddonModForumPost } from '@addons/mod/forum/services/forum' ;
1919import { PopoverController } from '@singletons' ;
20- import { CoreNetworkError } from '@classes/errors/network-error' ;
2120import { CoreSharedModule } from '@/core/shared.module' ;
2221import { CoreAlerts } from '@services/overlays/alerts' ;
22+ import { AddonModForumHelper } from '../../services/forum-helper' ;
2323
2424/**
2525 * This component is meant to display a popover with the post options.
@@ -32,69 +32,83 @@ import { CoreAlerts } from '@services/overlays/alerts';
3232 CoreSharedModule ,
3333 ] ,
3434} )
35- export class AddonModForumPostOptionsMenuComponent implements OnInit {
35+ export class AddonModForumPostOptionsMenuComponent {
3636
37- @ Input ( { required : true } ) post ! : AddonModForumPost ; // The post.
38- @ Input ( { required : true } ) cmId ! : number ;
39- @ Input ( { required : true } ) forumId ! : number ; // The forum Id.
37+ readonly post = input . required < AddonModForumPost > ( ) ; // The post.
38+ readonly cmId = input . required < number > ( ) ;
39+ readonly forumId = input . required < number > ( ) ; // The forum Id.
4040
41- canEdit = false ;
42- canDelete = false ;
43- loaded = false ;
44- url ?: string ;
45- offlinePost = false ;
41+ protected readonly postCalculated = linkedSignal ( ( ) => this . post ( ) ) ;
42+ readonly canEdit = computed ( ( ) => this . isOfflinePost ( ) || AddonModForumHelper . canUpdatePost ( this . postCalculated ( ) ) ) ;
43+
44+ readonly canDelete = computed ( ( ) => this . isOfflinePost ( ) || AddonModForumHelper . canDeletePost ( this . postCalculated ( ) ) ) ;
45+ readonly editDeleteDisabled = computed ( ( ) => this . unknownCapabilities ( ) || ( ! this . isOfflinePost ( ) && ! this . isOnline ( ) ) ) ;
46+
47+ readonly canMarkAsRead = computed ( ( ) =>
48+ ! this . isOfflinePost ( ) && AddonModForumHelper . canSetReadState ( this . postCalculated ( ) ) ) ;
49+
50+ readonly markAsReadDisabled = computed ( ( ) => this . unknownCapabilities ( ) || ! this . isOnline ( ) ) ;
51+
52+ readonly loaded = signal ( false ) ;
53+
54+ readonly isOfflinePost = computed ( ( ) => this . postCalculated ( ) . id < 0 ) ;
55+ protected readonly isOnline = CoreNetwork . onlineSignal ;
56+
57+ protected readonly unknownCapabilities = computed ( ( ) => {
58+ if ( this . isOfflinePost ( ) ) {
59+ return false ;
60+ }
61+
62+ const post = this . postCalculated ( ) ;
63+
64+ return post . capabilities . delete === undefined ;
65+ } ) ;
4666
4767 /**
4868 * @inheritdoc
4969 */
50- async ngOnInit ( ) : Promise < void > {
51- this . offlinePost = this . post . id < 0 ;
52- if ( this . offlinePost ) {
53- this . loaded = true ;
54-
55- return ;
56- }
70+ constructor ( ) {
71+ effect ( async ( ) => {
72+ const unknownCapabilities = this . unknownCapabilities ( ) ;
73+ const isOnline = this . isOnline ( ) ;
5774
58- if ( this . post . capabilities . delete === undefined ) {
59- if ( this . forumId ) {
60- try {
61- this . post =
62- await AddonModForum . getDiscussionPost ( this . forumId , this . post . discussionid , this . post . id , {
63- cmId : this . cmId ,
64- readingStrategy : CoreSitesReadingStrategy . ONLY_NETWORK ,
65- } ) ;
66- } catch ( error ) {
67- CoreAlerts . showError ( error , { default : 'Error getting discussion post.' } ) ;
68- }
69- } else {
70- this . loaded = true ;
71- // Display the open in browser button to prevent having an empty menu.
72- this . setOpenInBrowserUrl ( ) ;
75+ if ( ! unknownCapabilities ) {
76+ this . loaded . set ( true ) ;
7377
7478 return ;
7579 }
76- }
7780
78- this . canDelete = ! ! this . post . capabilities . delete && AddonModForum . isDeletePostAvailable ( ) ;
79- this . canEdit = ! ! this . post . capabilities . edit && AddonModForum . isUpdatePostAvailable ( ) ;
80- if ( ! this . canDelete && ! this . canEdit ) {
81- // Display the open in browser button to prevent having an empty menu.
82- this . setOpenInBrowserUrl ( ) ;
83- }
81+ // Only check this one because the others are always available if this one is.
82+ const wsAvailable = AddonModForum . isDeletePostAvailable ( ) ;
83+ if ( ! wsAvailable ) {
84+ // If the WS is not available, we cannot do anything.
85+ this . loaded . set ( true ) ;
8486
85- this . loaded = true ;
86- }
87+ return ;
88+ }
8789
88- /**
89- * Set the URL to open in browser.
90- */
91- protected setOpenInBrowserUrl ( ) : void {
92- const site = CoreSites . getRequiredCurrentSite ( ) ;
93- if ( ! site . shouldDisplayInformativeLinks ( ) ) {
94- return ;
95- }
90+ const forumId = this . forumId ( ) ;
91+ if ( forumId && isOnline ) {
92+ this . loaded . set ( false ) ;
93+
94+ await untracked ( async ( ) => {
95+ let post = this . postCalculated ( ) ;
96+
97+ try {
98+ post =
99+ await AddonModForum . getDiscussionPost ( forumId , post . discussionid , post . id , {
100+ cmId : this . cmId ( ) ,
101+ readingStrategy : CoreSitesReadingStrategy . ONLY_NETWORK ,
102+ } ) ;
103+ this . postCalculated . set ( post ) ;
104+ } catch ( error ) {
105+ CoreAlerts . showError ( error , { default : 'Error getting discussion post.' } ) ;
106+ }
107+ } ) ;
108+ }
96109
97- this . url = site . createSiteUrl ( '/mod/forum/discuss.php' , { d : this . post . discussionid . toString ( ) } , `p${ this . post . id } ` ) ;
110+ this . loaded . set ( true ) ;
111+ } ) ;
98112 }
99113
100114 /**
@@ -108,30 +122,37 @@ export class AddonModForumPostOptionsMenuComponent implements OnInit {
108122 * Delete a post.
109123 */
110124 deletePost ( ) : void {
111- if ( ! this . offlinePost ) {
112- if ( ! CoreNetwork . isOnline ( ) ) {
113- CoreAlerts . showError ( new CoreNetworkError ( ) ) ;
114-
115- return ;
116- }
117-
118- PopoverController . dismiss ( { action : 'delete' } ) ;
125+ if ( ! this . isOfflinePost ( ) ) {
126+ PopoverController . dismiss ( { action : AddonModForumPostOptionsMenuAction . DELETE } ) ;
119127 } else {
120- PopoverController . dismiss ( { action : 'deleteoffline' } ) ;
128+ PopoverController . dismiss ( { action : AddonModForumPostOptionsMenuAction . DELETE_OFFLINE } ) ;
121129 }
122130 }
123131
124132 /**
125133 * Edit a post.
126134 */
127135 editPost ( ) : void {
128- if ( ! this . offlinePost && ! CoreNetwork . isOnline ( ) ) {
129- CoreAlerts . showError ( new CoreNetworkError ( ) ) ;
130-
131- return ;
132- }
136+ PopoverController . dismiss ( { action : AddonModForumPostOptionsMenuAction . EDIT } ) ;
137+ }
133138
134- PopoverController . dismiss ( { action : 'edit' } ) ;
139+ /**
140+ * Toggle the read state of a post.
141+ */
142+ toggleReadState ( ) : void {
143+ PopoverController . dismiss ( {
144+ action : this . postCalculated ( ) . unread
145+ ? AddonModForumPostOptionsMenuAction . MARKREAD
146+ : AddonModForumPostOptionsMenuAction . MARKUNREAD ,
147+ } ) ;
135148 }
136149
137150}
151+
152+ export enum AddonModForumPostOptionsMenuAction {
153+ DELETE = 'delete' ,
154+ DELETE_OFFLINE = 'deleteoffline' ,
155+ EDIT = 'edit' ,
156+ MARKREAD = 'markread' ,
157+ MARKUNREAD = 'markunread' ,
158+ } ;
0 commit comments