diff --git a/swad_changelog.h b/swad_changelog.h index 64e4289d..d2d1d391 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -553,7 +553,7 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 20.14 (2021-02-08)" +#define Log_PLATFORM_VERSION "SWAD 20.14.1 (2021-02-08)" #define CSS_FILE "swad20.8.css" #define JS_FILE "swad20.6.2.js" /* @@ -600,6 +600,7 @@ TODO: DNI de un estudiante sale err TODO: BUG: Cuando un tipo de grupo sólo tiene un grupo, inscribirse es voluntario, el estudiante sólo puede pertenecer a un grupo, y se inscribe en él, debería poder desapuntarse. Ahora no puede. + Version 20.14.1: Feb 08, 2021 Code refactoring in timeline. (305072 lines) Version 20.14: Feb 08, 2021 New module timeline_shared. (305048 lines) Version 20.13: Feb 08, 2021 New module timeline_favourite. (304971 lines) Version 20.12.1: Feb 08, 2021 Code refactoring in timeline. (304900 lines) diff --git a/swad_string.c b/swad_string.c index 252a96e4..f86db413 100644 --- a/swad_string.c +++ b/swad_string.c @@ -680,6 +680,101 @@ static unsigned Str_FindHTMLEntity (const char *Ptr) 0; // No HTML entity found } +/*****************************************************************************/ +/*** Create a notification about mention for any nickname in a publication ***/ +/*****************************************************************************/ +/* + Example: "The user @rms says..." + ^ ^ + PtrStart ___| |___ PtrEnd + Length = 3 +*/ +void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt) + { + const char *Ptr; + bool IsNickname; + struct + { + const char *PtrStart; + const char *PtrEnd; + size_t Length; // Length of the nickname + } Nickname; + struct UsrData UsrDat; + bool ItsMe; + bool CreateNotif; + bool NotifyByEmail; + + /***** Initialize structure with user's data *****/ + Usr_UsrDataConstructor (&UsrDat); + + /***** Find nicknames and create notifications *****/ + for (Ptr = Txt; + *Ptr;) + /* Check if the next char is the start of a nickname */ + if ((int) *Ptr == (int) '@') + { + /* Find nickname end */ + Ptr++; // Points to first character after @ + Nickname.PtrStart = Ptr; + + /* A nick can have digits, letters and '_' */ + for (; + *Ptr; + Ptr++) + if (!((*Ptr >= 'a' && *Ptr <= 'z') || + (*Ptr >= 'A' && *Ptr <= 'Z') || + (*Ptr >= '0' && *Ptr <= '9') || + (*Ptr == '_'))) + break; + + /* Calculate length of this nickname */ + Nickname.PtrEnd = Ptr - 1; + Nickname.Length = (size_t) (Ptr - Nickname.PtrStart); + + /* A nick (without arroba) must have a number of characters + Nck_MIN_BYTES_NICKNAME_WITHOUT_ARROBA <= Length <= Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA */ + IsNickname = (Nickname.Length >= Nck_MIN_BYTES_NICKNAME_WITHOUT_ARROBA && + Nickname.Length <= Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA); + + if (IsNickname) + { + /* Copy nickname */ + strncpy (UsrDat.Nickname,Nickname.PtrStart,Nickname.Length); + UsrDat.Nickname[Nickname.Length] = '\0'; + + if ((UsrDat.UsrCod = Nck_GetUsrCodFromNickname (UsrDat.Nickname)) > 0) + { + ItsMe = Usr_ItsMe (UsrDat.UsrCod); + if (!ItsMe) // Not me + { + /* Get user's data */ + Usr_GetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS); + + /* Create notification for the mentioned user *****/ + CreateNotif = (UsrDat.NtfEvents.CreateNotif & (1 << Ntf_EVENT_TIMELINE_MENTION)); + if (CreateNotif) + { + NotifyByEmail = (UsrDat.NtfEvents.SendEmail & (1 << Ntf_EVENT_TIMELINE_MENTION)); + Ntf_StoreNotifyEventToOneUser (Ntf_EVENT_TIMELINE_MENTION,&UsrDat,PubCod, + (Ntf_Status_t) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL : + 0), + Gbl.Hierarchy.Ins.InsCod, + Gbl.Hierarchy.Ctr.CtrCod, + Gbl.Hierarchy.Deg.DegCod, + Gbl.Hierarchy.Crs.CrsCod); + } + } + } + } + } + /* The next char is not the start of a nickname */ + else // Character != '@' + Ptr++; + + /***** Free memory used for user's data *****/ + Usr_UsrDataDestructor (&UsrDat); + } + /*****************************************************************************/ /***** Convert a string to title: first uppercase and the rest lowercase *****/ /*****************************************************************************/ diff --git a/swad_string.h b/swad_string.h index 28ad21fb..9aabc11a 100644 --- a/swad_string.h +++ b/swad_string.h @@ -84,6 +84,9 @@ typedef enum void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen); size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen); + +void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt); + void Str_ConvertToTitleType (char *Str); void Str_ConvertToComparable (char *Str); char *Str_ConvertToUpperText (char *Str); diff --git a/swad_timeline.c b/swad_timeline.c index 88f73b2c..b0471dd9 100644 --- a/swad_timeline.c +++ b/swad_timeline.c @@ -32,9 +32,6 @@ #include // For string functions #include // For time_t -#include "swad_announcement.h" -#include "swad_box.h" -#include "swad_constant.h" #include "swad_database.h" #include "swad_exam_announcement.h" #include "swad_figure.h" @@ -42,13 +39,9 @@ #include "swad_form.h" #include "swad_forum.h" #include "swad_global.h" -#include "swad_HTML.h" -#include "swad_layout.h" -#include "swad_media.h" #include "swad_message.h" #include "swad_notice.h" -#include "swad_notification.h" -#include "swad_parameter.h" +#include "swad_photo.h" #include "swad_profile.h" #include "swad_setting.h" #include "swad_timeline.h" @@ -309,8 +302,6 @@ static void TL_ResetComment (struct TL_Comment *SocCom); static void TL_ClearTimelineThisSession (void); static void TL_AddNotesJustRetrievedToTimelineThisSession (void); -static void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt); - /*****************************************************************************/ /************************ Initialize global timeline *************************/ /*****************************************************************************/ @@ -4054,7 +4045,8 @@ void TL_RemoveUsrContent (long UsrCod) void TL_ShowNumSharersOrFavers (unsigned NumUsrs) { - /***** Show number of users who have marked this note as favourite *****/ + /***** Show number of sharers or favers + (users who have shared or marked this note as favourite) *****/ HTM_TxtF (" %u",NumUsrs); } @@ -4201,7 +4193,13 @@ static void TL_GetDataOfPublicationFromRow (MYSQL_ROW row,struct TL_Publication [TL_PUB_SHARED_NOTE ] = TL_TOP_MESSAGE_SHARED, [TL_PUB_COMMENT_TO_NOTE] = TL_TOP_MESSAGE_COMMENTED, }; - + /* + row[0]: PubCod + row[1]: NotCod + row[2]: PublisherCod + row[3]: PubType + row[4]: UNIX_TIMESTAMP(TimePublish) + */ /***** Get code of publication (row[0]) *****/ SocPub->PubCod = Str_ConvertStrCodToLongCod (row[0]); @@ -4225,6 +4223,15 @@ static void TL_GetDataOfPublicationFromRow (MYSQL_ROW row,struct TL_Publication static void TL_GetDataOfNoteFromRow (MYSQL_ROW row,struct TL_Note *SocNot) { + /* + row[0]: NotCod + row[1]: NoteType + row[2]: Cod + row[3]: UsrCod + row[4]: HieCod + row[5]: Unavailable + row[5]: UNIX_TIMESTAMP(TimeNote) + */ /***** Get code (row[0]) *****/ SocNot->NotCod = Str_ConvertStrCodToLongCod (row[0]); @@ -4296,7 +4303,7 @@ static void TL_GetDataOfCommentFromRow (MYSQL_ROW row,struct TL_Comment *SocCom) row[3]: TimePublish row[4]: Txt row[5]: MedCod - */ + */ /***** Get code of comment (row[0]) *****/ SocCom->PubCod = Str_ConvertStrCodToLongCod (row[0]); @@ -4523,101 +4530,6 @@ void TL_GetNotifPublication (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1], (*ContentStr)[0] = '\0'; } -/*****************************************************************************/ -/*** Create a notification about mention for any nickname in a publication ***/ -/*****************************************************************************/ -/* - Example: "The user @rms says..." - ^ ^ - PtrStart ___| |___ PtrEnd - Length = 3 -*/ -static void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt) - { - const char *Ptr; - bool IsNickname; - struct - { - const char *PtrStart; - const char *PtrEnd; - size_t Length; // Length of the nickname - } Nickname; - struct UsrData UsrDat; - bool ItsMe; - bool CreateNotif; - bool NotifyByEmail; - - /***** Initialize structure with user's data *****/ - Usr_UsrDataConstructor (&UsrDat); - - /***** Find nicknames and create notifications *****/ - for (Ptr = Txt; - *Ptr;) - /* Check if the next char is the start of a nickname */ - if ((int) *Ptr == (int) '@') - { - /* Find nickname end */ - Ptr++; // Points to first character after @ - Nickname.PtrStart = Ptr; - - /* A nick can have digits, letters and '_' */ - for (; - *Ptr; - Ptr++) - if (!((*Ptr >= 'a' && *Ptr <= 'z') || - (*Ptr >= 'A' && *Ptr <= 'Z') || - (*Ptr >= '0' && *Ptr <= '9') || - (*Ptr == '_'))) - break; - - /* Calculate length of this nickname */ - Nickname.PtrEnd = Ptr - 1; - Nickname.Length = (size_t) (Ptr - Nickname.PtrStart); - - /* A nick (without arroba) must have a number of characters - Nck_MIN_BYTES_NICKNAME_WITHOUT_ARROBA <= Length <= Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA */ - IsNickname = (Nickname.Length >= Nck_MIN_BYTES_NICKNAME_WITHOUT_ARROBA && - Nickname.Length <= Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA); - - if (IsNickname) - { - /* Copy nickname */ - strncpy (UsrDat.Nickname,Nickname.PtrStart,Nickname.Length); - UsrDat.Nickname[Nickname.Length] = '\0'; - - if ((UsrDat.UsrCod = Nck_GetUsrCodFromNickname (UsrDat.Nickname)) > 0) - { - ItsMe = Usr_ItsMe (UsrDat.UsrCod); - if (!ItsMe) // Not me - { - /* Get user's data */ - Usr_GetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS); - - /* Create notification for the mentioned user *****/ - CreateNotif = (UsrDat.NtfEvents.CreateNotif & (1 << Ntf_EVENT_TIMELINE_MENTION)); - if (CreateNotif) - { - NotifyByEmail = (UsrDat.NtfEvents.SendEmail & (1 << Ntf_EVENT_TIMELINE_MENTION)); - Ntf_StoreNotifyEventToOneUser (Ntf_EVENT_TIMELINE_MENTION,&UsrDat,PubCod, - (Ntf_Status_t) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL : - 0), - Gbl.Hierarchy.Ins.InsCod, - Gbl.Hierarchy.Ctr.CtrCod, - Gbl.Hierarchy.Deg.DegCod, - Gbl.Hierarchy.Crs.CrsCod); - } - } - } - } - } - /* The next char is not the start of a nickname */ - else // Character != '@' - Ptr++; - - /***** Free memory used for user's data *****/ - Usr_UsrDataDestructor (&UsrDat); - } - /*****************************************************************************/ /****************** Get number of publications from a user *******************/ /*****************************************************************************/ diff --git a/swad_timeline_favourite.c b/swad_timeline_favourite.c index a63257ac..ba789254 100644 --- a/swad_timeline_favourite.c +++ b/swad_timeline_favourite.c @@ -100,7 +100,7 @@ static void TL_Fav_PutDisabledIconFav (unsigned NumFavs) } /*****************************************************************************/ -/************************** Form to fav/unfav note ***************************/ +/************************ Form to show all favers ****************************/ /*****************************************************************************/ void TL_Fav_PutFormToSeeAllFaversNote (const struct TL_Note *SocNot, @@ -600,11 +600,10 @@ static void TL_Fav_ShowUsrsWhoHaveMarkedNoteAsFav (const struct TL_Note *SocNot, TL_HowManyUsrs_t HowManyUsrs) { MYSQL_RES *mysql_res; - unsigned NumFirstUsrs = 0; + unsigned NumFirstUsrs; /***** Get users who have marked this note as favourite *****/ if (SocNot->NumFavs) - { /***** Get list of users from database *****/ NumFirstUsrs = (unsigned) DB_QuerySELECT (&mysql_res,"can not get users", @@ -616,16 +615,20 @@ static void TL_Fav_ShowUsrsWhoHaveMarkedNoteAsFav (const struct TL_Note *SocNot, SocNot->UsrCod, HowManyUsrs == TL_SHOW_FEW_USRS ? TL_DEF_USRS_SHOWN : TL_MAX_USRS_SHOWN); - } + else + NumFirstUsrs = 0; /***** Show users *****/ + /* Number of users */ HTM_DIV_Begin ("class=\"TL_NUM_USRS\""); TL_ShowNumSharersOrFavers (SocNot->NumFavs); HTM_DIV_End (); + /* List users one by one */ HTM_DIV_Begin ("class=\"TL_USRS\""); TL_ShowSharersOrFavers (&mysql_res,SocNot->NumFavs,NumFirstUsrs); if (NumFirstUsrs < SocNot->NumFavs) // Not all are shown + /* Clickable ellipsis to show all users */ TL_Fav_PutFormToSeeAllFaversNote (SocNot,HowManyUsrs); HTM_DIV_End (); @@ -639,10 +642,10 @@ static void TL_Fav_ShowUsrsWhoHaveMarkedNoteAsFav (const struct TL_Note *SocNot, /*****************************************************************************/ static void TL_Fav_ShowUsrsWhoHaveMarkedCommAsFav (const struct TL_Comment *SocCom, - TL_HowManyUsrs_t HowManyUsrs) + TL_HowManyUsrs_t HowManyUsrs) { MYSQL_RES *mysql_res; - unsigned NumFirstUsrs = 0; + unsigned NumFirstUsrs; /***** Get users who have marked this comment as favourite *****/ if (SocCom->NumFavs) @@ -656,16 +659,21 @@ static void TL_Fav_ShowUsrsWhoHaveMarkedCommAsFav (const struct TL_Comment *SocC SocCom->PubCod, SocCom->UsrCod, HowManyUsrs == TL_SHOW_FEW_USRS ? TL_DEF_USRS_SHOWN : - TL_MAX_USRS_SHOWN); + TL_MAX_USRS_SHOWN); + else + NumFirstUsrs = 0; /***** Show users *****/ + /* Number of users */ HTM_DIV_Begin ("class=\"TL_NUM_USRS\""); TL_ShowNumSharersOrFavers (SocCom->NumFavs); HTM_DIV_End (); + /* List users one by one */ HTM_DIV_Begin ("class=\"TL_USRS\""); TL_ShowSharersOrFavers (&mysql_res,SocCom->NumFavs,NumFirstUsrs); if (NumFirstUsrs < SocCom->NumFavs) + /* Clickable ellipsis to show all users */ TL_Fav_PutFormToSeeAllFaversComment (SocCom,HowManyUsrs); HTM_DIV_End (); diff --git a/swad_timeline_share.c b/swad_timeline_share.c index 42e2f43f..87320f59 100644 --- a/swad_timeline_share.c +++ b/swad_timeline_share.c @@ -352,7 +352,7 @@ static void TL_Sha_ShowUsrsWhoHaveSharedNote (const struct TL_Note *SocNot, TL_HowManyUsrs_t HowManyUsrs) { MYSQL_RES *mysql_res; - unsigned NumFirstUsrs = 0; + unsigned NumFirstUsrs; /***** Get users who have shared this note *****/ if (SocNot->NumShared) @@ -367,16 +367,21 @@ static void TL_Sha_ShowUsrsWhoHaveSharedNote (const struct TL_Note *SocNot, SocNot->UsrCod, (unsigned) TL_PUB_SHARED_NOTE, HowManyUsrs == TL_SHOW_FEW_USRS ? TL_DEF_USRS_SHOWN : - TL_MAX_USRS_SHOWN); + TL_MAX_USRS_SHOWN); + else + NumFirstUsrs = 0; /***** Show users *****/ + /* Number of users */ HTM_DIV_Begin ("class=\"TL_NUM_USRS\""); TL_ShowNumSharersOrFavers (SocNot->NumShared); HTM_DIV_End (); + /* List users one by one */ HTM_DIV_Begin ("class=\"TL_USRS\""); TL_ShowSharersOrFavers (&mysql_res,SocNot->NumShared,NumFirstUsrs); if (NumFirstUsrs < SocNot->NumShared) + /* Clickable ellipsis to show all users */ TL_Sha_PutFormToSeeAllSharersNote (SocNot,HowManyUsrs); HTM_DIV_End ();