From 3ee4adff19b4d2d491d279d25a1ab13e55016b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Tue, 19 Jan 2016 00:50:35 +0100 Subject: [PATCH] Version 15.120 --- css/swad15.117.css | 7 +- icon/fav64x64.png | Bin 0 -> 1220 bytes icon/faved64x64.png | Bin 0 -> 1204 bytes icon/star-yellow64x64.png | Bin 0 -> 1204 bytes icon/star64x64.png | Bin 0 -> 1220 bytes sql/swad.sql | 8 +- swad_action.c | 26 ++- swad_action.h | 321 ++++++++++++------------- swad_changelog.h | 7 +- swad_database.c | 12 +- swad_layout.c | 24 +- swad_social.c | 479 +++++++++++++++++++++++++++++++++----- swad_social.h | 5 + swad_text.c | 126 ++++++++++ 14 files changed, 761 insertions(+), 254 deletions(-) create mode 100644 icon/fav64x64.png create mode 100644 icon/faved64x64.png create mode 100644 icon/star-yellow64x64.png create mode 100644 icon/star64x64.png diff --git a/css/swad15.117.css b/css/swad15.117.css index 01dae6cdd..4acb6f661 100644 --- a/css/swad15.117.css +++ b/css/swad15.117.css @@ -1763,19 +1763,20 @@ a:hover img.CENTRE_PHOTO_SHOW { display:inline-block; padding-top:10px; - padding-right:20px; vertical-align:bottom; } -.SOCIAL_ICON_SHARE +.SOCIAL_ICON_SHARE_FAV { display:inline-block; padding-top:10px; + padding-left:20px; vertical-align:bottom; } -.SOCIAL_ICON_SHARE_DISABLED +.SOCIAL_ICON_SHARE_FAV_DISABLED { display:inline-block; padding-top:10px; + padding-left:20px; opacity:0.2; vertical-align:bottom; } diff --git a/icon/fav64x64.png b/icon/fav64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..89ff9430a733daac8bae11a4e572148d5bb2508a GIT binary patch literal 1220 zcmV;#1UvhQP)eSad^g zZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00b~eL_t(&-tCxMY!p=($A2@s+Z$LQ zM%tJzY?Rg%rCgMTR*h$STY^d&jaFhX#fLudVxxdhY9c;iV!&d2=Rsph3?^DFtGkCL zBwQpIFpWUaMM@;nVr?p&c4udNXr-6EpV=)j+3#u2eCP5%-}OHO1u4k?S(*V5_v&~7 z1j-hpE&%Vq4M#)%n;F?PkfZ#_!>qvv2FTkQsny`DQlbOU!!XG1oflQEF{BZrr%= zWN@h{F-%M?#-QtxdA?+@`1Ds3|0%c8mmEM#X|%MoDZ1L;WL4{%tsK%94g0KqMLXxd zVFZhe;GKj3n(pHhYiItsl>WKdH87qa2;D2~Cl`avS@n8F!a{WQFP}z0ogri>Ht)-C z69N#((>@b_ULn}LBR>>G5&?)HG&$fK!>>+N)5sM2mX8N8dlR<=hcA`(zJ9(sx6FJXK>_&p4s%adp7*yc;?oh-A`^BeZJ4feqJ< zMwaC0{9DW4>^s<^g);92?Hoh2@fr8$;P?^k)o_11$Fk=GqKSUo4v#kp$dFPy7RV57 zm=2F`lOdtT2P8t1VFC;*A3sb$hUe#fR-7<`K>p?%q(vnhwPF4BaKA{yl=TcgLN0S# zDe*_FU(yrx407F7sZ}cFewE9c6HaKaV7Zb7mRRLE0I);X9W*`Pe3-y zi-s}XtfrgI*rdEDo9$-(D$)51F06GF1Ma8i4bQOW2XF8=ENrq80h|bh)@W~WX5J31 zjsTc-cPCyh>a+r~2ii!~WF_zd5bm)9`YW!xKZ?v+M*v*<471s#Z+h*>z$n1+q_e*S z;KXR?3(w>1nr2e^xTC*h8_!Oxq?Z@vxmD4RvM4}RQTdba5R?2-vFGOre zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00bOKL_t(|+U=TKh)q!#$A5Fo zurfoGqGnJsGD;b@qG()49<*NMK{1L%DH9JKcp>FQLnB^1xa5I6tWrv9=E;legLp7e zZY6hxR%19G=G)p$=d#Z}d)7MV*#BC!&))0y{nvL{>stp>q)3q>g?m_&`}w~T-Wn!a z!^HoJgplxU*6>nFn=cYFt_M{5-{VnWhLoctzSS-PveL_dj?k+PdFLGU9@M`9*a}Pu zeVPJnwTAn^FPEB7=VA3*fY*6GPgj~ZwQd5(Vt%V$0z#g@73eBZwM*(aiwI5#2-)UHggeI$8?F;H1sDG}w zUkuLn1$7QqzfjyShEd-axG;fZp4z%2AfLCkhS^2pelc`OACbo#brY~AzjwBVX>z)o z1xy3B0qteZ@eyzdcn7=yUMbBxCq5vbu-2e}l|U=7R0N(U8dWc4j5xp~@C*123`zL| zJQYIj0?&YlO7p3d1uIB^HH-%ounuSj7Ky-1Dm>?M4;TO*0B?cYfK{5GkqNMdCg41< zh1$SXV5ic2kLm=c0*k2~EEbufMFFLG4)g-q8W27U^omT;2oT3{8aPtrBxHdjN^?42 z*ev7(>y##I4c)*AU~H8MKL{LBnw~(G*kRBb_5i1tzBygFvo)voFij<*MJ631k6w3aFzrCV}O|+2$-3~ zCM;8?`U8vuFaPhE4>Xi}KafNiY$V#PZ_=0mG*&_wY{wrKRDusENBzG`iHnVuK)}41 zf?oqRNVx`liP6vOawi|#i-ykKD@ts79XKlosQ`DZVFj=c*jz$iD@V+wWR#uXvnKLE zqz~8+3@D8aMUj7#mpjK+h7+)>BlbHjh=G(`ycA!9Vlm{(*D?vZN`?&6=FzQ#?FB1MW6wTQpVia^+7 Sz>I|e0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00bOKL_t(|+U=TKh)q!#$A5Fo zurfoGqGnJsGD;b@qG()49<*NMK{1L%DH9JKcp>FQLnB^1xa5I6tWrv9=E;legLp7e zZY6hxR%19G=G)p$=d#Z}d)7MV*#BC!&))0y{nvL{>stp>q)3q>g?m_&`}w~T-Wn!a z!^HoJgplxU*6>nFn=cYFt_M{5-{VnWhLoctzSS-PveL_dj?k+PdFLGU9@M`9*a}Pu zeVPJnwTAn^FPEB7=VA3*fY*6GPgj~ZwQd5(Vt%V$0z#g@73eBZwM*(aiwI5#2-)UHggeI$8?F;H1sDG}w zUkuLn1$7QqzfjyShEd-axG;fZp4z%2AfLCkhS^2pelc`OACbo#brY~AzjwBVX>z)o z1xy3B0qteZ@eyzdcn7=yUMbBxCq5vbu-2e}l|U=7R0N(U8dWc4j5xp~@C*123`zL| zJQYIj0?&YlO7p3d1uIB^HH-%ounuSj7Ky-1Dm>?M4;TO*0B?cYfK{5GkqNMdCg41< zh1$SXV5ic2kLm=c0*k2~EEbufMFFLG4)g-q8W27U^omT;2oT3{8aPtrBxHdjN^?42 z*ev7(>y##I4c)*AU~H8MKL{LBnw~(G*kRBb_5i1tzBygFvo)voFij<*MJ631k6w3aFzrCV}O|+2$-3~ zCM;8?`U8vuFaPhE4>Xi}KafNiY$V#PZ_=0mG*&_wY{wrKRDusENBzG`iHnVuK)}41 zf?oqRNVx`liP6vOawi|#i-ykKD@ts79XKlosQ`DZVFj=c*jz$iD@V+wWR#uXvnKLE zqz~8+3@D8aMUj7#mpjK+h7+)>BlbHjh=G(`ycA!9Vlm{(*D?vZN`?&6=FzQ#?FB1MW6wTQpVia^+7 Sz>I|e0000eSad^g zZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00b~eL_t(&-tCxMY!p=($A2@s+Z$LQ zM%tJzY?Rg%rCgMTR*h$STY^d&jaFhX#fLudVxxdhY9c;iV!&d2=Rsph3?^DFtGkCL zBwQpIFpWUaMM@;nVr?p&c4udNXr-6EpV=)j+3#u2eCP5%-}OHO1u4k?S(*V5_v&~7 z1j-hpE&%Vq4M#)%n;F?PkfZ#_!>qvv2FTkQsny`DQlbOU!!XG1oflQEF{BZrr%= zWN@h{F-%M?#-QtxdA?+@`1Ds3|0%c8mmEM#X|%MoDZ1L;WL4{%tsK%94g0KqMLXxd zVFZhe;GKj3n(pHhYiItsl>WKdH87qa2;D2~Cl`avS@n8F!a{WQFP}z0ogri>Ht)-C z69N#((>@b_ULn}LBR>>G5&?)HG&$fK!>>+N)5sM2mX8N8dlR<=hcA`(zJ9(sx6FJXK>_&p4s%adp7*yc;?oh-A`^BeZJ4feqJ< zMwaC0{9DW4>^s<^g);92?Hoh2@fr8$;P?^k)o_11$Fk=GqKSUo4v#kp$dFPy7RV57 zm=2F`lOdtT2P8t1VFC;*A3sb$hUe#fR-7<`K>p?%q(vnhwPF4BaKA{yl=TcgLN0S# zDe*_FU(yrx407F7sZ}cFewE9c6HaKaV7Zb7mRRLE0I);X9W*`Pe3-y zi-s}XtfrgI*rdEDo9$-(D$)51F06GF1Ma8i4bQOW2XF8=ENrq80h|bh)@W~WX5J31 zjsTc-cPCyh>a+r~2ii!~WF_zd5bm)9`YW!xKZ?v+M*v*<471s#Z+h*>z$n1+q_e*S z;KXR?3(w>1nr2e^xTC*h8_!Oxq?Z@vxmD4RvM4}RQTdba5R?2-vFGOr DESCRIBE social_comments; "UNIQUE INDEX(ComCod)," "FULLTEXT(Content)) ENGINE = MYISAM;"); - /***** Table social_comments_favs *****/ + /***** Table social_comments_fav *****/ /* -mysql> DESCRIBE social_comments_favs; +mysql> DESCRIBE social_comments_fav; +--------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+------------+------+-----+---------+-------+ @@ -1968,7 +1968,7 @@ mysql> DESCRIBE social_comments_favs; +--------+------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) */ - DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_comments_favs (" + DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_comments_fav (" "ComCod BIGINT NOT NULL," "UsrCod INT NOT NULL," "UNIQUE INDEX(ComCod,UsrCod)," @@ -2003,9 +2003,9 @@ mysql> DESCRIBE social_notes; "INDEX(UsrCod)," "INDEX(TimeNote))"); - /***** Table social_notes_favs *****/ + /***** Table social_notes_fav *****/ /* -mysql> DESCRIBE social_notes_favs; +mysql> DESCRIBE social_notes_fav; +--------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+------------+------+-----+---------+-------+ @@ -2014,7 +2014,7 @@ mysql> DESCRIBE social_notes_favs; +--------+------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) */ - DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_notes_favs (" + DB_CreateTable ("CREATE TABLE IF NOT EXISTS social_notes_fav (" "NotCod BIGINT NOT NULL," "UsrCod INT NOT NULL," "UNIQUE INDEX(NotCod,UsrCod)," diff --git a/swad_layout.c b/swad_layout.c index 330180a34..3dd8ad5ef 100644 --- a/swad_layout.c +++ b/swad_layout.c @@ -614,7 +614,9 @@ static void Lay_WriteScriptInit (void) Gbl.Action.Act == ActRcvSocPstGbl || Gbl.Action.Act == ActRcvSocComGbl || Gbl.Action.Act == ActShaSocNotGbl || - Gbl.Action.Act == ActUnsSocPubGbl || + Gbl.Action.Act == ActUnsSocNotGbl || + Gbl.Action.Act == ActFavSocNotGbl || + Gbl.Action.Act == ActUnfSocNotGbl || Gbl.Action.Act == ActReqRemSocPubGbl || Gbl.Action.Act == ActRemSocPubGbl || Gbl.Action.Act == ActReqRemSocComGbl || @@ -649,7 +651,9 @@ static void Lay_WriteScriptParamsAJAX (void) Gbl.Action.Act == ActRcvSocPstGbl || Gbl.Action.Act == ActRcvSocComGbl || Gbl.Action.Act == ActShaSocNotGbl || - Gbl.Action.Act == ActUnsSocPubGbl || + Gbl.Action.Act == ActUnsSocNotGbl || + Gbl.Action.Act == ActFavSocNotGbl || + Gbl.Action.Act == ActUnfSocNotGbl || Gbl.Action.Act == ActReqRemSocPubGbl || Gbl.Action.Act == ActRemSocPubGbl || Gbl.Action.Act == ActReqRemSocComGbl || @@ -662,14 +666,16 @@ static void Lay_WriteScriptParamsAJAX (void) Act_Actions[ActRefNewSocPubGbl].ActCod, Act_Actions[ActRefOldSocPubGbl].ActCod); else if (Gbl.Action.Act == ActSeePubPrf || - Gbl.Action.Act == ActRcvSocPstGbl || + Gbl.Action.Act == ActRcvSocPstUsr || Gbl.Action.Act == ActRcvSocComUsr || - Gbl.Action.Act == ActShaSocNotGbl || - Gbl.Action.Act == ActUnsSocPubGbl || - Gbl.Action.Act == ActReqRemSocPubGbl || - Gbl.Action.Act == ActRemSocPubGbl || - Gbl.Action.Act == ActReqRemSocComGbl || - Gbl.Action.Act == ActRemSocComGbl) + Gbl.Action.Act == ActShaSocNotUsr || + Gbl.Action.Act == ActUnsSocNotUsr || + Gbl.Action.Act == ActFavSocNotUsr || + Gbl.Action.Act == ActUnfSocNotUsr || + Gbl.Action.Act == ActReqRemSocPubUsr || + Gbl.Action.Act == ActRemSocPubUsr || + Gbl.Action.Act == ActReqRemSocComUsr || + Gbl.Action.Act == ActRemSocComUsr) { /* In all the actions related to view or editing user's timeline ==> put parameters used by AJAX */ diff --git a/swad_social.c b/swad_social.c index 028ff3bd3..1aa3b5eae 100644 --- a/swad_social.c +++ b/swad_social.c @@ -80,6 +80,16 @@ typedef enum // when user clicks on link at bottom of timeline } Soc_WhatToGetFromTimeline_t; +typedef enum + { + Soc_TOP_MESSAGE_NONE, + Soc_TOP_MESSAGE_SHARED, + Soc_TOP_MESSAGE_UNSHARED, + Soc_TOP_MESSAGE_FAV, + Soc_TOP_MESSAGE_UNFAV, + Soc_TOP_MESSAGE_COMMENTED, + } Soc_TopMessage_t; + static const Act_Action_t Soc_DefaultActions[Soc_NUM_NOTE_TYPES] = { ActUnk, // Soc_NOTE_UNKNOWN @@ -167,6 +177,7 @@ struct SocialPublishing long PublisherCod; // Sharer or writer of a comment Soc_PubType_t PubType; time_t DateTimeUTC; + Soc_TopMessage_t TopMessage; // Used to show feedback on the action made }; struct SocialNote @@ -179,6 +190,7 @@ struct SocialNote bool Unavailable; // File, forum post, notice,... unavailable (removed) time_t DateTimeUTC; unsigned NumShared; // Number of times (users) this note has been shared + unsigned NumFavs; // Number of times (users) this note has been favourited }; struct SocialComment @@ -229,10 +241,11 @@ static void Soc_PutLinkToViewNewPublishings (void); static void Soc_PutLinkToViewOldPublishings (void); static void Soc_WriteSocialNote (const struct SocialNote *SocNot, - const struct SocialPublishing *SocPub, + Soc_TopMessage_t TopMessage, + long UsrCod, bool Highlight, bool ShowNoteAlone); -static void Soc_WriteTopPublisher (const struct SocialPublishing *SocPub); +static void Soc_WriteTopPublisher (Soc_TopMessage_t TopMessage,long UsrCod); static void Soc_WriteAuthorNote (struct UsrData *UsrDat); static void Soc_WriteDateTime (time_t TimeUTC); static void Soc_GetAndWriteSocialPost (long PstCod); @@ -257,9 +270,16 @@ static void Soc_WriteSocialComment (struct SocialComment *SocCom, bool ShowCommentAlone); static void Soc_WriteAuthorComment (struct UsrData *UsrDat); static void Soc_PutFormToRemoveComment (long ComCod); + static void Soc_PutDisabledIconShare (unsigned NumShared); +static void Soc_PutDisabledIconFav (unsigned NumFavs); + static void Soc_PutFormToShareSocialNote (long NotCod); -static void Soc_PutFormToUnshareSocialPublishing (long NotCod); +static void Soc_PutFormToFavSocialNote (long NotCod); + +static void Soc_PutFormToUnshareSocialNote (long NotCod); +static void Soc_PutFormToUnfavSocialNote (long NotCod); + static void Soc_PutFormToRemoveSocialPublishing (long NotCod); static void Soc_PutHiddenParamNotCod (long NotCod); @@ -270,8 +290,11 @@ static long Soc_GetParamComCod (void); static long Soc_ReceiveComment (void); static long Soc_ShareSocialNote (void); +static long Soc_FavSocialNote (void); + static long Soc_UnshareSocialNote (void); static void Soc_UnshareASocialPublishingFromDB (struct SocialNote *SocNot); +static long Soc_UnfavSocialNote (void); static void Soc_RequestRemovalSocialNote (void); static void Soc_RemoveSocialNote (void); @@ -282,7 +305,11 @@ static void Soc_RemoveSocialComment (void); static void Soc_RemoveASocialCommentFromDB (struct SocialComment *SocCom); static bool Soc_CheckIfNoteIsPublishedInTimelineByUsr (long NotCod,long UsrCod); +static bool Soc_CheckIfNoteIsFavouritedByUsr (long NotCod,long UsrCod); + static void Soc_UpdateNumTimesANoteHasBeenShared (struct SocialNote *SocNot); +static void Soc_UpdateNumTimesANoteHasBeenFav (struct SocialNote *SocNot); + static void Soc_ShowUsrsWhoHaveSharedSocialNote (const struct SocialNote *SocNot); static void Soc_GetDataOfSocialNoteByCod (struct SocialNote *SocNot); @@ -831,7 +858,8 @@ static void Soc_ShowTimeline (const char *Query,const char *Title, Soc_GetDataOfSocialNoteByCod (&SocNot); /* Write social note */ - Soc_WriteSocialNote (&SocNot,&SocPub, + Soc_WriteSocialNote (&SocNot, + SocPub.TopMessage,SocPub.PublisherCod, SocNot.NotCod == NotCodToHighlight, false); } @@ -887,7 +915,9 @@ static void Soc_InsertNewPubsInTimeline (const char *Query) Soc_GetDataOfSocialNoteByCod (&SocNot); /* Write social note */ - Soc_WriteSocialNote (&SocNot,&SocPub,false,false); + Soc_WriteSocialNote (&SocNot, + SocPub.TopMessage,SocPub.PublisherCod, + false,false); } /***** Free structure that stores the query result *****/ @@ -925,7 +955,9 @@ static void Soc_ShowOldPubsInTimeline (const char *Query) Soc_GetDataOfSocialNoteByCod (&SocNot); /* Write social note */ - Soc_WriteSocialNote (&SocNot,&SocPub,false,false); + Soc_WriteSocialNote (&SocNot, + SocPub.TopMessage,SocPub.PublisherCod, + false,false); } /***** Store first publishing code into session *****/ @@ -985,7 +1017,8 @@ static void Soc_PutLinkToViewOldPublishings (void) // All forms in this function and nested functions must have unique identifiers static void Soc_WriteSocialNote (const struct SocialNote *SocNot, - const struct SocialPublishing *SocPub, + Soc_TopMessage_t TopMessage, + long UsrCod, bool Highlight, // Highlight social note bool ShowNoteAlone) // Social note is shown alone, not in a list { @@ -997,6 +1030,7 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, struct UsrData UsrDat; bool IAmTheAuthor = false; bool IAmAPublisherOfThisSocNot = false; + bool IAmAFavouriterOfThisSocNot = false; struct Institution Ins; struct Centre Ctr; struct Degree Deg; @@ -1041,8 +1075,7 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, Crs.CrsCod = -1L; /***** Write sharer/commenter if distinct to author *****/ - if (SocPub) // SocPub may be NULL - Soc_WriteTopPublisher (SocPub); + Soc_WriteTopPublisher (TopMessage,UsrCod); /***** Initialize structure with user's data *****/ Usr_UsrDataConstructor (&UsrDat); @@ -1055,6 +1088,8 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, IAmTheAuthor = (UsrDat.UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); IAmAPublisherOfThisSocNot = Soc_CheckIfNoteIsPublishedInTimelineByUsr (SocNot->NotCod, Gbl.Usrs.Me.UsrDat.UsrCod); + IAmAFavouriterOfThisSocNot = Soc_CheckIfNoteIsFavouritedByUsr (SocNot->NotCod, + Gbl.Usrs.Me.UsrDat.UsrCod); } /***** Left: write author's photo *****/ @@ -1198,7 +1233,7 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, else if (IAmAPublisherOfThisSocNot) // I am a sharer of this social note, // but not the author ==> I have shared this social note /* Put icon to unshare this publishing */ - Soc_PutFormToUnshareSocialPublishing (SocNot->NotCod); + Soc_PutFormToUnshareSocialNote (SocNot->NotCod); else // I am not the author and I am not a sharer { if (SocNot->Unavailable) // Unavailable social notes can not be shared @@ -1211,7 +1246,22 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, /* Show who have shared this social note */ Soc_ShowUsrsWhoHaveSharedSocialNote (SocNot); - /* Put icon to remove this publishing */ + /* Put icon to mark this social note as favourite */ + if (IAmTheAuthor) // I am the author + Soc_PutDisabledIconFav (SocNot->NumFavs); + else if (IAmAFavouriterOfThisSocNot) // I have favourited this social note + /* Put icon to unfav this publishing */ + Soc_PutFormToUnfavSocialNote (SocNot->NotCod); + else // I am not the author and I am not a sharer + { + if (SocNot->Unavailable) // Unavailable social notes can not be favourited + Soc_PutDisabledIconFav (SocNot->NumFavs); + else + /* Put icon to share this publishing */ + Soc_PutFormToFavSocialNote (SocNot->NotCod); + } + + /* Put icon to remove this social note */ if (IAmTheAuthor) Soc_PutFormToRemoveSocialPublishing (SocNot->NotCod); @@ -1245,56 +1295,63 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot, /*****************************************************************************/ // All forms in this function and nested functions must have unique identifiers -static void Soc_WriteTopPublisher (const struct SocialPublishing *SocPub) +static void Soc_WriteTopPublisher (Soc_TopMessage_t TopMessage,long UsrCod) { extern const char *Txt_View_public_profile; - extern const char *Txt_SOCIAL_USER_has_stopped_sharing; extern const char *Txt_SOCIAL_USER_has_shared; + extern const char *Txt_SOCIAL_USER_has_stopped_sharing; + extern const char *Txt_SOCIAL_USER_has_marked_as_favourite; + extern const char *Txt_SOCIAL_USER_has_unmarked_as_favourite; extern const char *Txt_SOCIAL_USER_has_commented; struct UsrData UsrDat; - if (SocPub) - if (SocPub->PubType != Soc_PUB_ORIGINAL_NOTE) + if (TopMessage != Soc_TOP_MESSAGE_NONE) + { + /***** Initialize structure with user's data *****/ + Usr_UsrDataConstructor (&UsrDat); + + /***** Get user's data *****/ + UsrDat.UsrCod = UsrCod; + if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) // Really we only need EncryptedUsrCod and FullName { - /***** Initialize structure with user's data *****/ - Usr_UsrDataConstructor (&UsrDat); + fprintf (Gbl.F.Out,"
"); - /***** Get user's data *****/ - UsrDat.UsrCod = SocPub->PublisherCod; - if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) // Really we only need EncryptedUsrCod and FullName + /***** Show user's name inside form to go to user's public profile *****/ + Act_FormStartUnique (ActSeePubPrf); + Usr_PutParamUsrCodEncrypted (UsrDat.EncryptedUsrCod); + Act_LinkFormSubmitUnique (Txt_View_public_profile,"SOCIAL_TOP_PUBLISHER"); + Str_LimitLengthHTMLStr (UsrDat.FullName,40); + fprintf (Gbl.F.Out,"%s",UsrDat.FullName); + Act_FormEnd (); + + /***** Show action made *****/ + switch (TopMessage) { - fprintf (Gbl.F.Out,"
"); - - /***** Show user's name inside form to go to user's public profile *****/ - Act_FormStartUnique (ActSeePubPrf); - Usr_PutParamUsrCodEncrypted (UsrDat.EncryptedUsrCod); - Act_LinkFormSubmitUnique (Txt_View_public_profile,"SOCIAL_TOP_PUBLISHER"); - Str_LimitLengthHTMLStr (UsrDat.FullName,40); - fprintf (Gbl.F.Out,"%s",UsrDat.FullName); - Act_FormEnd (); - - /***** Show action made *****/ - switch (SocPub->PubType) - { - case Soc_PUB_UNKNOWN: // Used to print message indicating that I have unshared - fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_stopped_sharing); - break; - case Soc_PUB_ORIGINAL_NOTE: // Not applicable - break; - case Soc_PUB_SHARED_NOTE: - fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_shared); - break; - case Soc_PUB_COMMENT_TO_NOTE: - fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_commented); - break; - } - - fprintf (Gbl.F.Out,"
"); + case Soc_TOP_MESSAGE_NONE: // Not applicable + break; + case Soc_TOP_MESSAGE_SHARED: + fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_shared); + break; + case Soc_TOP_MESSAGE_UNSHARED: + fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_stopped_sharing); + break; + case Soc_TOP_MESSAGE_FAV: + fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_marked_as_favourite); + break; + case Soc_TOP_MESSAGE_UNFAV: + fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_unmarked_as_favourite); + break; + case Soc_TOP_MESSAGE_COMMENTED: + fprintf (Gbl.F.Out," %s",Txt_SOCIAL_USER_has_commented); + break; } - /***** Free memory used for user's data *****/ - Usr_UsrDataDestructor (&UsrDat); + fprintf (Gbl.F.Out,"
"); } + + /***** Free memory used for user's data *****/ + Usr_UsrDataDestructor (&UsrDat); + } } /*****************************************************************************/ @@ -2217,7 +2274,7 @@ static void Soc_PutDisabledIconShare (unsigned NumShared) strcpy (Gbl.Title,Txt_SOCIAL_NOTE_Not_shared_by_anyone); /***** Disabled icon to share *****/ - fprintf (Gbl.F.Out,"
" + fprintf (Gbl.F.Out,"
" "\"%s\"" @@ -2226,6 +2283,30 @@ static void Soc_PutDisabledIconShare (unsigned NumShared) Gbl.Title,Gbl.Title); } +/*****************************************************************************/ +/****************** Put disabled icon to mark as favourite *******************/ +/*****************************************************************************/ + +static void Soc_PutDisabledIconFav (unsigned NumFavs) + { + extern const char *Txt_SOCIAL_NOTE_Favourited_by_X_USERS; + extern const char *Txt_SOCIAL_NOTE_Not_favourited_by_anyone; + + if (NumFavs) + sprintf (Gbl.Title,Txt_SOCIAL_NOTE_Favourited_by_X_USERS,NumFavs); + else + strcpy (Gbl.Title,Txt_SOCIAL_NOTE_Not_favourited_by_anyone); + + /***** Disabled icon to mark as favourite *****/ + fprintf (Gbl.F.Out,"
" + "\"%s\"" + "
", + Gbl.Prefs.IconsURL, + Gbl.Title,Gbl.Title); + } + /*****************************************************************************/ /************************* Form to share social note *************************/ /*****************************************************************************/ @@ -2244,7 +2325,7 @@ static void Soc_PutFormToShareSocialNote (long NotCod) else Act_FormStartUnique (ActShaSocNotGbl); Soc_PutHiddenParamNotCod (NotCod); - fprintf (Gbl.F.Out,"
" + fprintf (Gbl.F.Out,"
" " 0) + { + Act_FormStartUniqueAnchor (ActFavSocNotUsr,"timeline"); + Usr_PutParamOtherUsrCodEncrypted (); + } + else + Act_FormStartUnique (ActFavSocNotGbl); + Soc_PutHiddenParamNotCod (NotCod); + fprintf (Gbl.F.Out,"
" + "" + "
", + Gbl.Prefs.IconsURL, + Txt_Mark_as_favourite,Txt_Mark_as_favourite); + Act_FormEnd (); + } + +/*****************************************************************************/ +/*************** Form to unshare (stop sharing) social note ******************/ +/*****************************************************************************/ +// All forms in this function and nested functions must have unique identifiers + +static void Soc_PutFormToUnshareSocialNote (long NotCod) { extern const char *Txt_Unshare; /***** Form to share social publishing *****/ if (Gbl.Usrs.Other.UsrDat.UsrCod > 0) { - Act_FormStartUniqueAnchor (ActUnsSocPubUsr,"timeline"); + Act_FormStartUniqueAnchor (ActUnsSocNotUsr,"timeline"); Usr_PutParamOtherUsrCodEncrypted (); } else - Act_FormStartUnique (ActUnsSocPubGbl); + Act_FormStartUnique (ActUnsSocNotGbl); Soc_PutHiddenParamNotCod (NotCod); - fprintf (Gbl.F.Out,"
" + fprintf (Gbl.F.Out,"
" " 0) + { + Act_FormStartUniqueAnchor (ActUnfSocNotUsr,"timeline"); + Usr_PutParamOtherUsrCodEncrypted (); + } + else + Act_FormStartUnique (ActUnfSocNotGbl); + Soc_PutHiddenParamNotCod (NotCod); + fprintf (Gbl.F.Out,"
" + "" + "
", + Gbl.Prefs.IconsURL, + Txt_Favourite,Txt_Favourite); + Act_FormEnd (); + } + /*****************************************************************************/ /******************** Form to remove social publishing ***********************/ /*****************************************************************************/ @@ -2440,7 +2579,9 @@ static long Soc_ReceiveComment (void) DB_QueryINSERT (Query,"can not store comment content"); /***** Show the social note just commented *****/ - Soc_WriteSocialNote (&SocNot,&SocPub,true,true); + Soc_WriteSocialNote (&SocNot, + Soc_TOP_MESSAGE_COMMENTED,Gbl.Usrs.Me.UsrDat.UsrCod, + true,true); } } else @@ -2531,6 +2672,92 @@ static long Soc_ShareSocialNote (void) return SocNot.NotCod; } +/*****************************************************************************/ +/********************** Mark a social note as favourite **********************/ +/*****************************************************************************/ + +void Soc_FavSocialNoteGbl (void) + { + long NotCod; + + /***** Mark social note as favourite *****/ + NotCod = Soc_FavSocialNote (); + + /***** Write updated timeline after marking as favourite (global) *****/ + Soc_ShowTimelineGblHighlightingNot (NotCod); + } + +void Soc_FavSocialNoteUsr (void) + { + long NotCod; + + /***** Get user whom profile is displayed *****/ + Usr_GetParamOtherUsrCodEncryptedAndGetUsrData (); + + /***** Show user's profile *****/ + Prf_ShowUserProfile (); + + /***** Start section *****/ + fprintf (Gbl.F.Out,"
"); + + /***** Mark social note as favourite *****/ + NotCod = Soc_FavSocialNote (); + + /***** Write updated timeline after marking as favourite (user) *****/ + Soc_ShowTimelineUsrHighlightingNot (NotCod); + + /***** End section *****/ + fprintf (Gbl.F.Out,"
"); + } + +static long Soc_FavSocialNote (void) + { + extern const char *Txt_The_original_post_no_longer_exists; + struct SocialNote SocNot; + bool IAmTheAuthor; + bool IAmAFavouriterOfThisSocNot; + bool ICanFav; + char Query[256]; + + /***** Get the code of the social note to mark as favourite *****/ + SocNot.NotCod = Soc_GetParamNotCod (); + + /***** Get data of social note *****/ + Soc_GetDataOfSocialNoteByCod (&SocNot); + + if (SocNot.NotCod > 0) + { + IAmTheAuthor = (SocNot.UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); + IAmAFavouriterOfThisSocNot = Soc_CheckIfNoteIsFavouritedByUsr (SocNot.NotCod, + Gbl.Usrs.Me.UsrDat.UsrCod); + ICanFav = (Gbl.Usrs.Me.Logged && + !IAmTheAuthor && // I am not the author + !IAmAFavouriterOfThisSocNot); // I have not favourited the note + if (ICanFav) + { + /***** Mark as favourite in database *****/ + sprintf (Query,"INSERT IGNORE INTO social_notes_fav" + " (NotCod,UsrCod) VALUES ('%ld','%ld')", + SocNot.NotCod, + Gbl.Usrs.Me.UsrDat.UsrCod); + DB_QueryINSERT (Query,"can not favourite social note"); + + /* Update number of times this social note is favourited */ + Soc_UpdateNumTimesANoteHasBeenFav (&SocNot); + + /***** Show the social note corresponding + to the publishing just fav *****/ + Soc_WriteSocialNote (&SocNot, + Soc_TOP_MESSAGE_FAV,Gbl.Usrs.Me.UsrDat.UsrCod, + true,true); + } + } + else + Lay_ShowAlert (Lay_WARNING,Txt_The_original_post_no_longer_exists); + + return SocNot.NotCod; + } + /*****************************************************************************/ /***************** Unshare a previously shared social note *******************/ /*****************************************************************************/ @@ -2553,7 +2780,7 @@ void Soc_UnshareSocialNoteUsr (void) /***** Get user whom profile is displayed *****/ Usr_GetParamOtherUsrCodEncryptedAndGetUsrData (); - /***** Show user's profile *****/ + /***** Show user's profile *****/ Prf_ShowUserProfile (); /***** Start section *****/ @@ -2572,7 +2799,6 @@ void Soc_UnshareSocialNoteUsr (void) static long Soc_UnshareSocialNote (void) { struct SocialNote SocNot; - struct SocialPublishing SocPub; // Used to print message indicating that I have unshared bool IAmTheAuthor; bool IAmAPublisherOfThisSocNot; bool ICanUnshare; @@ -2600,9 +2826,9 @@ static long Soc_UnshareSocialNote (void) /***** Show the social note corresponding to the publishing just unshared *****/ - SocPub.PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod; - SocPub.PubType = Soc_PUB_UNKNOWN; // Used to print message indicating that I have unshared - Soc_WriteSocialNote (&SocNot,&SocPub,true,true); + Soc_WriteSocialNote (&SocNot, + Soc_TOP_MESSAGE_UNSHARED,Gbl.Usrs.Me.UsrDat.UsrCod, + true,true); } return SocNot.NotCod; @@ -2627,6 +2853,84 @@ static void Soc_UnshareASocialPublishingFromDB (struct SocialNote *SocNot) DB_QueryDELETE (Query,"can not remove a social publishing"); } +/*****************************************************************************/ +/******* Stop marking as favourite a previously favourited social note *******/ +/*****************************************************************************/ + +void Soc_UnfavSocialNoteGbl (void) + { + long NotCod; + + /***** Stop marking as favourite a previously favourited social note *****/ + NotCod = Soc_UnfavSocialNote (); + + /***** Write updated timeline after unfav (global) *****/ + Soc_ShowTimelineGblHighlightingNot (NotCod); + } + +void Soc_UnfavSocialNoteUsr (void) + { + long NotCod; + + /***** Get user whom profile is displayed *****/ + Usr_GetParamOtherUsrCodEncryptedAndGetUsrData (); + + /***** Show user's profile *****/ + Prf_ShowUserProfile (); + + /***** Start section *****/ + fprintf (Gbl.F.Out,"
"); + + /***** Unshare a previously shared social note *****/ + NotCod = Soc_UnfavSocialNote (); + + /***** Write updated timeline after unfav (user) *****/ + Soc_ShowTimelineUsrHighlightingNot (NotCod); + + /***** End section *****/ + fprintf (Gbl.F.Out,"
"); + } + +static long Soc_UnfavSocialNote (void) + { + struct SocialNote SocNot; + bool IAmTheAuthor; + bool IAmAFavouriterOfThisSocNot; + bool ICanUnfav; + char Query[256]; + + /***** Get data of social note *****/ + SocNot.NotCod = Soc_GetParamNotCod (); + Soc_GetDataOfSocialNoteByCod (&SocNot); + + IAmTheAuthor = (SocNot.UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod); + IAmAFavouriterOfThisSocNot = Soc_CheckIfNoteIsFavouritedByUsr (SocNot.NotCod, + Gbl.Usrs.Me.UsrDat.UsrCod); + ICanUnfav = (Gbl.Usrs.Me.Logged && + !IAmTheAuthor && // I am not the author + IAmAFavouriterOfThisSocNot); // I have favourited the note + if (ICanUnfav) + { + /***** Delete the mark as favourite from database *****/ + sprintf (Query,"DELETE FROM social_notes_fav" + " WHERE NotCod='%ld' AND UsrCod='%ld'", + SocNot.NotCod, + Gbl.Usrs.Me.UsrDat.UsrCod); + DB_QueryDELETE (Query,"can not unfavourite social note"); + + /***** Update number of times this social note is favourited *****/ + Soc_UpdateNumTimesANoteHasBeenFav (&SocNot); + + /***** Show the social note corresponding + to the publishing just unfavourited *****/ + Soc_WriteSocialNote (&SocNot, + Soc_TOP_MESSAGE_UNFAV,Gbl.Usrs.Me.UsrDat.UsrCod, + true,true); + } + + return SocNot.NotCod; + } + /*****************************************************************************/ /******************* Request the removal of a social note ********************/ /*****************************************************************************/ @@ -2683,7 +2987,9 @@ static void Soc_RequestRemovalSocialNote (void) Lay_ShowAlert (Lay_WARNING,Txt_Do_you_really_want_to_remove_the_following_post); /* Show social note */ - Soc_WriteSocialNote (&SocNot,NULL,false,true); + Soc_WriteSocialNote (&SocNot, + Soc_TOP_MESSAGE_NONE,-1L, + false,true); /***** Form to ask for confirmation to remove this social post *****/ /* Start form */ @@ -3051,6 +3357,20 @@ static bool Soc_CheckIfNoteIsPublishedInTimelineByUsr (long NotCod,long UsrCod) return (DB_QueryCOUNT (Query,"can not check if a user has published a social note") != 0); } +/*****************************************************************************/ +/*************** Check if a user has favourited a social note ****************/ +/*****************************************************************************/ + +static bool Soc_CheckIfNoteIsFavouritedByUsr (long NotCod,long UsrCod) + { + char Query[256]; + + sprintf (Query,"SELECT COUNT(*) FROM social_notes_fav" + " WHERE NotCod='%ld' AND UsrCod='%ld'", + NotCod,UsrCod); + return (DB_QueryCOUNT (Query,"can not check if a user has favourited a social note") != 0); + } + /*****************************************************************************/ /******** Get number of times a note code has been shared in timeline ********/ /*****************************************************************************/ @@ -3070,6 +3390,23 @@ static void Soc_UpdateNumTimesANoteHasBeenShared (struct SocialNote *SocNot) SocNot->NumShared = (unsigned) DB_QueryCOUNT (Query,"can not get number of times a note has been shared"); } +/*****************************************************************************/ +/************ Get number of times a note code has been favourited ************/ +/*****************************************************************************/ + +static void Soc_UpdateNumTimesANoteHasBeenFav (struct SocialNote *SocNot) + { + char Query[256]; + + /***** Get number of times (users) this note has been favourited *****/ + sprintf (Query,"SELECT COUNT(*) FROM social_notes_fav" + " WHERE NotCod='%ld'" + " AND UsrCod<>'%ld'", // Extra check + SocNot->NotCod, + SocNot->UsrCod); // The author + SocNot->NumFavs = (unsigned) DB_QueryCOUNT (Query,"can not get number of times a note has been favourited"); + } + /*****************************************************************************/ /**************** Show users who have shared this social note ****************/ /*****************************************************************************/ @@ -3176,6 +3513,9 @@ static void Soc_GetDataOfSocialNoteByCod (struct SocialNote *SocNot) /***** Get number of times this social note has been shared *****/ Soc_UpdateNumTimesANoteHasBeenShared (SocNot); + + /***** Get number of times this social note has been favourited *****/ + Soc_UpdateNumTimesANoteHasBeenFav (SocNot); } else /***** Reset fields of social note *****/ @@ -3240,6 +3580,19 @@ static void Soc_GetDataOfSocialPublishingFromRow (MYSQL_ROW row,struct SocialPub /* Get type of publishing (row[3]) */ SocPub->PubType = Soc_GetPubTypeFromStr ((const char *) row[3]); + switch (SocPub->PubType) + { + case Soc_PUB_UNKNOWN: + case Soc_PUB_ORIGINAL_NOTE: + SocPub->TopMessage = Soc_TOP_MESSAGE_NONE; + break; + case Soc_PUB_SHARED_NOTE: + SocPub->TopMessage = Soc_TOP_MESSAGE_SHARED; + break; + case Soc_PUB_COMMENT_TO_NOTE: + SocPub->TopMessage = Soc_TOP_MESSAGE_COMMENTED; + break; + } /* Get time of the note (row[4]) */ SocPub->DateTimeUTC = Dat_GetUNIXTimeFromStr (row[4]); diff --git a/swad_social.h b/swad_social.h index 2f5678087..e25fdcc79 100644 --- a/swad_social.h +++ b/swad_social.h @@ -113,8 +113,13 @@ void Soc_ReceiveCommentUsr (void); void Soc_ShareSocialNoteGbl (void); void Soc_ShareSocialNoteUsr (void); +void Soc_FavSocialNoteGbl (void); +void Soc_FavSocialNoteUsr (void); + void Soc_UnshareSocialNoteGbl (void); void Soc_UnshareSocialNoteUsr (void); +void Soc_UnfavSocialNoteGbl (void); +void Soc_UnfavSocialNoteUsr (void); void Soc_RequestRemSocialNoteGbl (void); void Soc_RequestRemSocialNoteUsr (void); diff --git a/swad_text.c b/swad_text.c index 719e60a06..ffc119958 100644 --- a/swad_text.c +++ b/swad_text.c @@ -11055,6 +11055,27 @@ const char *Txt_Family_address = "Endereço Família"; #endif +const char *Txt_Favourite = +#if L==1 + "Favorit"; +#elif L==2 + "Favorit"; +#elif L==3 + "Favourite"; +#elif L==4 + "Favorito"; +#elif L==5 + "Favori"; +#elif L==6 + "Favorito"; // Okoteve traducción +#elif L==7 + "Preferito"; +#elif L==8 + "Ulubiony"; +#elif L==9 + "Favorito"; +#endif + const char *Txt_Feedback = #if L==1 "Realimentación"; // Necessita traduccio @@ -16403,6 +16424,27 @@ const char *Txt_Mark_all_notifications_as_read = "Marcar todas as notificações como lidas"; #endif +const char *Txt_Mark_as_favourite = +#if L==1 + "Marca com favorit"; +#elif L==2 + "Markieren als Favorit"; +#elif L==3 + "Mark as favourite"; +#elif L==4 + "Marcar como favorito"; +#elif L==5 + "Marquer comme favori"; +#elif L==6 + "Marcar como favorito"; // Okoteve traducción +#elif L==7 + "Segnare come preferito"; +#elif L==8 + "Oznacz jako ulubiony"; +#elif L==9 + "Marcar como favorito"; +#endif + const char *Txt_Marks_management_area = #if L==1 "Zona d'administració de qualificacions"; @@ -35740,6 +35782,27 @@ const char *Txt_SOCIAL_NOTE[Soc_NUM_NOTE_TYPES] = #endif }; +const char *Txt_SOCIAL_NOTE_Favourited_by_X_USERS = // Warning: it is very important to include %u in the following sentences +#if L==1 + "Marcat com favorit per %u"; +#elif L==2 + "Von %u vorgemerkt"; +#elif L==3 + "Favourited by %u"; +#elif L==4 + "Marcado como favorito por %u"; +#elif L==5 + "Ajouté aux favoris par %u"; +#elif L==6 + "Marcado como favorito por %u"; // Okoteve traducción +#elif L==7 + "Preferiti da %u"; +#elif L==8 + "Dodane do ulubionych przez %u"; +#elif L==9 + "Marcado como favorito por %u"; +#endif + const char *Txt_SOCIAL_NOTE_Shared_by_X_USERS = // Warning: it is very important to include %u in the following sentences #if L==1 "Compartit per %u"; @@ -35761,6 +35824,27 @@ const char *Txt_SOCIAL_NOTE_Shared_by_X_USERS = // Warning: it is very important "Compartilhado por %u"; #endif +const char *Txt_SOCIAL_NOTE_Not_favourited_by_anyone = // No longer shared +#if L==1 + "No marcat com favorit per ningú"; +#elif L==2 + "Niemand hat sie als Favorit markiert"; +#elif L==3 + "Not favourited by anyone"; +#elif L==4 + "No marcado como favorito por nadie"; +#elif L==5 + "Personne n'a marqué comme favori"; +#elif L==6 + "No marcado como favorito por nadie"; // Okoteve traducción +#elif L==7 + "Non preferiti da chiunque"; +#elif L==8 + "Nie przez nikogo ulubionych"; +#elif L==9 + "Não marcado como favorito por qualquer pessoa"; +#endif + const char *Txt_SOCIAL_NOTE_Not_shared_by_anyone = // No longer shared #if L==1 "No compartit per ningú"; @@ -35803,6 +35887,27 @@ const char *Txt_SOCIAL_USER_has_commented = "comentou:"; #endif +const char *Txt_SOCIAL_USER_has_marked_as_favourite = +#if L==1 + "ha marcat com favorit:"; +#elif L==2 + "hat als Favorit markiert:"; +#elif L==3 + "has marked as favourite:"; +#elif L==4 + "ha marcado como favorito:"; +#elif L==5 + "a marqué en tant que favori:"; +#elif L==6 + "ha marcado como favorito:"; // Okoteve traducción +#elif L==7 + "ha segnato come preferito:"; +#elif L==8 + "oznaczone jako ulubiony:"; +#elif L==9 + "marcou como favorito:"; +#endif + const char *Txt_SOCIAL_USER_has_shared = #if L==1 "ha compartit:"; @@ -35845,6 +35950,27 @@ const char *Txt_SOCIAL_USER_has_stopped_sharing = "parou compartilhar:"; #endif +const char *Txt_SOCIAL_USER_has_unmarked_as_favourite = +#if L==1 + "ha desmarcat com favorit:"; +#elif L==2 + "hat als Favorit unmarkiert:"; +#elif L==3 + "has unmarked as favourite:"; +#elif L==4 + "ha desmarcado como favorito:"; +#elif L==5 + "a pas marqué en tant que favori:"; +#elif L==6 + "ha desmarcado como favorito:"; // Okoteve traducción +#elif L==7 + "ha smarcato come preferito:"; +#elif L==8 + "nieoznaczonych jako ulubiony:"; +#elif L==9 + "desmarcou como favorito:"; +#endif + const char *Txt_Sort_degrees_by = #if L==1 "Ordenar titulacions per";