Settings to opt-out of certain notification types
This commit is contained in:
parent
64d2749299
commit
c0bff8ee18
|
@ -63,9 +63,12 @@ var (
|
|||
"interests",
|
||||
"music_movies",
|
||||
"hide_age",
|
||||
}
|
||||
|
||||
// Site prefs
|
||||
// "dm_privacy", "blur_explicit",
|
||||
// Site preference names (stored in ProfileField table)
|
||||
SitePreferenceFields = []string{
|
||||
"dm_privacy",
|
||||
"blur_explicit",
|
||||
}
|
||||
|
||||
// Choices for the Contact Us subject
|
||||
|
@ -112,3 +115,27 @@ type Option struct {
|
|||
Value string
|
||||
Label string
|
||||
}
|
||||
|
||||
// NotificationOptout field values (stored in user ProfileField table)
|
||||
const (
|
||||
NotificationOptOutFriendPhotos = "notif_optout_friends_photos"
|
||||
NotificationOptOutPrivatePhotos = "notif_optout_private_photos"
|
||||
NotificationOptOutExplicitPhotos = "notif_optout_explicit_photos"
|
||||
NotificationOptOutLikes = "notif_optout_likes"
|
||||
NotificationOptOutComments = "notif_optout_comments"
|
||||
NotificationOptOutSubscriptions = "notif_optout_subscriptions"
|
||||
NotificationOptOutFriendRequestAccepted = "notif_optout_friend_request_accepted"
|
||||
NotificationOptOutPrivateGrant = "notif_optout_private_grant"
|
||||
)
|
||||
|
||||
// Notification opt-outs (stored in ProfileField table)
|
||||
var NotificationOptOutFields = []string{
|
||||
NotificationOptOutFriendPhotos,
|
||||
NotificationOptOutPrivatePhotos,
|
||||
NotificationOptOutExplicitPhotos,
|
||||
NotificationOptOutLikes,
|
||||
NotificationOptOutComments,
|
||||
NotificationOptOutSubscriptions,
|
||||
NotificationOptOutFriendRequestAccepted,
|
||||
NotificationOptOutPrivateGrant,
|
||||
}
|
||||
|
|
|
@ -164,6 +164,44 @@ func Settings() http.HandlerFunc {
|
|||
}
|
||||
|
||||
session.Flash(w, r, "Privacy settings updated!")
|
||||
case "notifications":
|
||||
hashtag = "#notifications"
|
||||
|
||||
// Store their notification opt-outs.
|
||||
for _, key := range config.NotificationOptOutFields {
|
||||
var value = r.PostFormValue(key)
|
||||
|
||||
// Boolean flip for DB storage:
|
||||
// - Pre-existing users before these options are added have no pref stored in the DB
|
||||
// - The default pref is opt-IN (receive all notifications)
|
||||
// - The checkboxes on front-end are on by default, uncheck them to opt-out, checkbox value="true"
|
||||
// - So when they post as "true" (default), we keep the notifications sending
|
||||
// - If they uncheck the box, no value is sent and that's an opt-out.
|
||||
if value == "" {
|
||||
value = "true" // opt-out, store opt-out=true in the DB
|
||||
} else if value == "true" {
|
||||
value = "false" // the box remained checked, they don't opt-out, store opt-out=false in the DB
|
||||
}
|
||||
|
||||
// Save it. TODO: fires off inserts/updates for each one,
|
||||
// probably not performant to do.
|
||||
user.SetProfileField(key, value)
|
||||
}
|
||||
session.Flash(w, r, "Notification preferences updated!")
|
||||
|
||||
// Save the user for new fields to be committed to DB.
|
||||
if err := user.Save(); err != nil {
|
||||
session.FlashError(w, r, "Failed to save user to database: %s", err)
|
||||
}
|
||||
|
||||
// Are they unsubscribing from all threads?
|
||||
if r.PostFormValue("unsubscribe_all_threads") == "true" {
|
||||
if err := models.UnsubscribeAllThreads(user); err != nil {
|
||||
session.FlashError(w, r, "Couldn't unsubscribe from threads: %s", err)
|
||||
} else {
|
||||
session.Flash(w, r, "Unsubscribed from all comment threads!")
|
||||
}
|
||||
}
|
||||
case "location":
|
||||
hashtag = "#location"
|
||||
var (
|
||||
|
@ -293,6 +331,9 @@ func Settings() http.HandlerFunc {
|
|||
// Show enabled status for 2FA.
|
||||
vars["TwoFactorEnabled"] = models.Get2FA(user.ID).Enabled
|
||||
|
||||
// Count of subscribed comment threads.
|
||||
vars["SubscriptionCount"] = models.CountSubscriptions(user)
|
||||
|
||||
if err := tmpl.Execute(w, r, vars); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
@ -181,7 +181,7 @@ func Likes() http.HandlerFunc {
|
|||
|
||||
// Notify the recipient of the like.
|
||||
log.Info("Added like on %s:%d, notifying owner %+v", req.TableName, tableID, targetUser)
|
||||
if targetUser != nil {
|
||||
if targetUser != nil && !targetUser.NotificationOptOut(config.NotificationOptOutLikes) {
|
||||
notif := &models.Notification{
|
||||
UserID: targetUser.ID,
|
||||
AboutUser: *currentUser,
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.nonshy.com/nonshy/website/pkg/config"
|
||||
"code.nonshy.com/nonshy/website/pkg/log"
|
||||
"code.nonshy.com/nonshy/website/pkg/models"
|
||||
"code.nonshy.com/nonshy/website/pkg/session"
|
||||
|
@ -109,6 +110,9 @@ func PostComment() http.HandlerFunc {
|
|||
|
||||
// Are we DELETING this comment?
|
||||
if isDelete {
|
||||
// Revoke notifications.
|
||||
models.RemoveNotification("comments", comment.ID)
|
||||
|
||||
if err := comment.Delete(); err != nil {
|
||||
session.FlashError(w, r, "Error deleting your commenting: %s", err)
|
||||
} else {
|
||||
|
@ -165,7 +169,7 @@ func PostComment() http.HandlerFunc {
|
|||
templates.Redirect(w, fromURL)
|
||||
|
||||
// Notify the recipient of the comment.
|
||||
if notifyUser != nil && notifyUser.ID != currentUser.ID {
|
||||
if notifyUser != nil && notifyUser.ID != currentUser.ID && !notifyUser.NotificationOptOut(config.NotificationOptOutComments) {
|
||||
notif := &models.Notification{
|
||||
UserID: notifyUser.ID,
|
||||
AboutUser: *currentUser,
|
||||
|
@ -206,10 +210,12 @@ func PostComment() http.HandlerFunc {
|
|||
|
||||
// Subscribe the current user to this comment thread, so they are
|
||||
// notified if other users add followup comments.
|
||||
if _, err := models.SubscribeTo(currentUser, comment.TableName, comment.TableID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to comment thread %s/%d: %s",
|
||||
currentUser.ID, comment.TableName, comment.TableID, err,
|
||||
)
|
||||
if !currentUser.NotificationOptOut(config.NotificationOptOutSubscriptions) {
|
||||
if _, err := models.SubscribeTo(currentUser, comment.TableName, comment.TableID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to comment thread %s/%d: %s",
|
||||
currentUser.ID, comment.TableName, comment.TableID, err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -366,8 +366,10 @@ func NewPost() http.HandlerFunc {
|
|||
}
|
||||
|
||||
// Subscribe the current user to further responses on this thread.
|
||||
if _, err := models.SubscribeTo(currentUser, "threads", thread.ID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to forum thread %d: %s", currentUser.ID, thread.ID, err)
|
||||
if !currentUser.NotificationOptOut(config.NotificationOptOutSubscriptions) {
|
||||
if _, err := models.SubscribeTo(currentUser, "threads", thread.ID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to forum thread %d: %s", currentUser.ID, thread.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect the poster to the correct page number too.
|
||||
|
@ -420,8 +422,10 @@ func NewPost() http.HandlerFunc {
|
|||
}
|
||||
|
||||
// Subscribe the current user to responses on this thread.
|
||||
if _, err := models.SubscribeTo(currentUser, "threads", thread.ID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to forum thread %d: %s", currentUser.ID, thread.ID, err)
|
||||
if !currentUser.NotificationOptOut(config.NotificationOptOutSubscriptions) {
|
||||
if _, err := models.SubscribeTo(currentUser, "threads", thread.ID); err != nil {
|
||||
log.Error("Couldn't subscribe user %d to forum thread %d: %s", currentUser.ID, thread.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
templates.Redirect(w, fmt.Sprintf("/forum/thread/%d", thread.ID))
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.nonshy.com/nonshy/website/pkg/config"
|
||||
"code.nonshy.com/nonshy/website/pkg/log"
|
||||
"code.nonshy.com/nonshy/website/pkg/models"
|
||||
"code.nonshy.com/nonshy/website/pkg/session"
|
||||
|
@ -87,13 +88,15 @@ func AddFriend() http.HandlerFunc {
|
|||
} else {
|
||||
if verdict == "approve" {
|
||||
// Notify the requestor they'd been approved.
|
||||
notif := &models.Notification{
|
||||
UserID: user.ID,
|
||||
AboutUser: *currentUser,
|
||||
Type: models.NotificationFriendApproved,
|
||||
}
|
||||
if err := models.CreateNotification(notif); err != nil {
|
||||
log.Error("Couldn't create approved notification: %s", err)
|
||||
if !user.NotificationOptOut(config.NotificationOptOutFriendRequestAccepted) {
|
||||
notif := &models.Notification{
|
||||
UserID: user.ID,
|
||||
AboutUser: *currentUser,
|
||||
Type: models.NotificationFriendApproved,
|
||||
}
|
||||
if err := models.CreateNotification(notif); err != nil {
|
||||
log.Error("Couldn't create approved notification: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
session.Flash(w, r, "You accepted the friend request from %s!", username)
|
||||
|
|
|
@ -213,6 +213,9 @@ func Delete() http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// Take back notifications on it.
|
||||
models.RemoveNotification("photos", photo.ID)
|
||||
|
||||
if err := photo.Delete(); err != nil {
|
||||
session.FlashError(w, r, "Couldn't delete photo: %s", err)
|
||||
templates.Redirect(w, redirect)
|
||||
|
|
|
@ -138,16 +138,18 @@ func Share() http.HandlerFunc {
|
|||
templates.Redirect(w, "/photo/private")
|
||||
|
||||
// Create a notification for this.
|
||||
notif := &models.Notification{
|
||||
UserID: user.ID,
|
||||
AboutUser: *currentUser,
|
||||
Type: models.NotificationPrivatePhoto,
|
||||
TableName: "__private_photos",
|
||||
TableID: currentUser.ID,
|
||||
Link: fmt.Sprintf("/photo/u/%s?visibility=private", currentUser.Username),
|
||||
}
|
||||
if err := models.CreateNotification(notif); err != nil {
|
||||
log.Error("Couldn't create PrivatePhoto notification: %s", err)
|
||||
if !user.NotificationOptOut(config.NotificationOptOutPrivateGrant) {
|
||||
notif := &models.Notification{
|
||||
UserID: user.ID,
|
||||
AboutUser: *currentUser,
|
||||
Type: models.NotificationPrivatePhoto,
|
||||
TableName: "__private_photos",
|
||||
TableID: currentUser.ID,
|
||||
Link: fmt.Sprintf("/photo/u/%s?visibility=private", currentUser.Username),
|
||||
}
|
||||
if err := models.CreateNotification(notif); err != nil {
|
||||
log.Error("Couldn't create PrivatePhoto notification: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -208,6 +208,9 @@ func notifyFriendsNewPhoto(photo *models.Photo, currentUser *models.User) {
|
|||
// You should not get notified about their new private photos.
|
||||
notifyUserIDs = models.FilterFriendIDs(notifyUserIDs, friendIDs)
|
||||
|
||||
// Filter down the notifyUserIDs further to respect their notification opt-out preferences.
|
||||
notifyUserIDs = models.FilterPhotoUploadNotificationUserIDs(photo, notifyUserIDs)
|
||||
|
||||
for _, fid := range notifyUserIDs {
|
||||
notif := &models.Notification{
|
||||
UserID: fid,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"code.nonshy.com/nonshy/website/pkg/config"
|
||||
"code.nonshy.com/nonshy/website/pkg/log"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
@ -75,7 +76,6 @@ func CreateNotification(n *Notification) error {
|
|||
time.Now(),
|
||||
time.Now(),
|
||||
).Error
|
||||
// return DB.Create(n).Error
|
||||
}
|
||||
|
||||
// GetNotification by ID.
|
||||
|
@ -85,6 +85,11 @@ func GetNotification(id uint64) (*Notification, error) {
|
|||
return n, result.Error
|
||||
}
|
||||
|
||||
// NotificationOptOut checks whether the user opts-out of a class of notification.
|
||||
func (u *User) NotificationOptOut(name string) bool {
|
||||
return u.GetProfileField(name) == "true"
|
||||
}
|
||||
|
||||
// RemoveNotification about a table ID, e.g. when removing a like.
|
||||
func RemoveNotification(tableName string, tableID uint64) error {
|
||||
result := DB.Where(
|
||||
|
@ -218,6 +223,67 @@ func PaginateNotifications(user *User, pager *Pagination) ([]*Notification, erro
|
|||
return ns, result.Error
|
||||
}
|
||||
|
||||
// FilterPhotoUploadNotificationUserIDs will narrow a set of UserIDs who would be notified about
|
||||
// a new photo upload to respect each user's preference for notification opt-outs.
|
||||
//
|
||||
// It is assumed that userIDs are already narrowed down to Friends of the current user.
|
||||
func FilterPhotoUploadNotificationUserIDs(photo *Photo, userIDs []uint64) []uint64 {
|
||||
var (
|
||||
result = []uint64{}
|
||||
|
||||
// Collect notification opt-out profile fields and map them by user ID for easy lookup.
|
||||
prefs = []*ProfileField{}
|
||||
mapPrefs = map[uint64]map[string]bool{}
|
||||
)
|
||||
if len(userIDs) == 0 {
|
||||
return userIDs
|
||||
}
|
||||
|
||||
// Collect opt-out preferences for these users.
|
||||
r := DB.Model(&ProfileField{}).Where(
|
||||
"user_id IN ? AND name IN ?",
|
||||
userIDs, []string{
|
||||
config.NotificationOptOutFriendPhotos, // all friends' photos
|
||||
config.NotificationOptOutPrivatePhotos, // private photos from friends
|
||||
config.NotificationOptOutExplicitPhotos, // explicit photos
|
||||
},
|
||||
).Find(&prefs)
|
||||
if r.Error != nil {
|
||||
log.Error("FilterPhotoUploadNotificationUserIDs: couldn't collect user preferences: %s", r.Error)
|
||||
}
|
||||
|
||||
// Map the preferences by user ID.
|
||||
for _, row := range prefs {
|
||||
if _, ok := mapPrefs[row.UserID]; !ok {
|
||||
mapPrefs[row.UserID] = map[string]bool{}
|
||||
}
|
||||
mapPrefs[row.UserID][row.Name] = row.Value == "true"
|
||||
}
|
||||
|
||||
// Narrow the notification recipients based on photo property and their preferences.
|
||||
for _, userID := range userIDs {
|
||||
// Skip explicit photo notification?
|
||||
if photo.Explicit && mapPrefs[userID][config.NotificationOptOutExplicitPhotos] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip private photo notification?
|
||||
if photo.Visibility == PhotoPrivate && mapPrefs[userID][config.NotificationOptOutPrivatePhotos] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip friend photo notifications?
|
||||
if mapPrefs[userID][config.NotificationOptOutFriendPhotos] {
|
||||
continue
|
||||
}
|
||||
|
||||
// They get the notification.
|
||||
result = append(result, userID)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Save a notification.
|
||||
func (n *Notification) Save() error {
|
||||
return DB.Save(n).Error
|
||||
|
|
|
@ -28,6 +28,29 @@ func GetSubscription(user *User, tableName string, tableID uint64) (*Subscriptio
|
|||
return s, result.Error
|
||||
}
|
||||
|
||||
// CountSubscriptions counts how many comment threads the user is subscribed to.
|
||||
func CountSubscriptions(user *User) int64 {
|
||||
var (
|
||||
count int64
|
||||
result = DB.Model(&Subscription{}).Where(
|
||||
"user_id = ? AND subscribed IS TRUE",
|
||||
user.ID,
|
||||
).Count(&count)
|
||||
)
|
||||
if result.Error != nil {
|
||||
log.Error("Error in CountSubscriptions(%s): %s", user.Username, result.Error)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// UnsubscribeAllThreads removes subscription preferences for all comment threads.
|
||||
func UnsubscribeAllThreads(user *User) error {
|
||||
return DB.Where(
|
||||
"user_id = ?",
|
||||
user.ID,
|
||||
).Delete(&Subscription{}).Error
|
||||
}
|
||||
|
||||
// GetSubscribers returns all of the UserIDs that are subscribed to a thread.
|
||||
func GetSubscribers(tableName string, tableID uint64) []uint64 {
|
||||
var userIDs = []uint64{}
|
||||
|
|
|
@ -315,6 +315,13 @@
|
|||
<hr>
|
||||
</div>
|
||||
|
||||
<p class="block">
|
||||
<a href="/settings#notifications">
|
||||
<i class="fa fa-gear mr-1"></i>
|
||||
Manage notification settings
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<table class="table is-striped is-fullwidth is-hoverable">
|
||||
<tbody>
|
||||
{{range .Notifications}}
|
||||
|
|
|
@ -61,6 +61,15 @@
|
|||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/settings#notifications" class="nonshy-tab-button">
|
||||
<strong><i class="fa fa-bell mr-1"></i> Notifications</strong>
|
||||
<p class="help">
|
||||
Control your (on-site) notification preferences.
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/settings#account" class="nonshy-tab-button">
|
||||
<strong><i class="fa fa-user mr-1"></i> Account Settings</strong>
|
||||
|
@ -655,6 +664,192 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification Settings -->
|
||||
<div class="card mb-5" id="notifications">
|
||||
<header class="card-header has-background-link">
|
||||
<p class="card-header-title has-text-light">
|
||||
<i class="fa fa-bell pr-2"></i>
|
||||
Notification Settings
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="card-content">
|
||||
<p class="block">
|
||||
On this page you may opt-out of certain kinds of (on-site) notification messages.
|
||||
{{PrettyTitle}} does not send you any e-mails or push notification -- these on-site
|
||||
notifications only appear while you are visiting the website (on your
|
||||
<a href="/me">home/user dashboard page</a>).
|
||||
</p>
|
||||
|
||||
<form method="POST" action="/settings">
|
||||
{{InputCSRF}}
|
||||
<input type="hidden" name="intent" value="notifications">
|
||||
|
||||
<h2 class="subtitle">New Photo Uploads</h2>
|
||||
|
||||
<p class="block">
|
||||
By default you will be notified when your friends upload a new picture to the site.
|
||||
Below, you may opt-out of new photo upload notifications.
|
||||
</p>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Notify me when...</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_friends_photos"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_friends_photos") "true"}}checked{{end}}>
|
||||
My friends upload a new photo
|
||||
</label>
|
||||
<p class="help">
|
||||
If unchecked, the following two notifications will not be sent either.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_private_photos"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_private_photos") "true"}}checked{{end}}>
|
||||
A friend who shared their private photos with me uploads a new private photo
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_explicit_photos"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_explicit_photos") "true"}}checked{{end}}>
|
||||
Allow notifications for 'explicit' photo uploads by my friends
|
||||
</label>
|
||||
<p class="help">
|
||||
This will also depend on your <a href="/settings#prefs" target="_blank">opt-in to see explicit content</a> -- otherwise
|
||||
notifications about explicit photo uploads will not be sent to you.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 class="subtitle mt-5">Likes & Comments</h2>
|
||||
|
||||
<p class="block">
|
||||
By default you will be notified when somebody 'likes' or comments on your profile page
|
||||
or photos. You may turn off those notifications with the options below.
|
||||
</p>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Notify me when...</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_likes"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_likes") "true"}}checked{{end}}>
|
||||
Somebody 'likes' my profile page, photos, or comments
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_comments"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_comments") "true"}}checked{{end}}>
|
||||
Somebody leaves a comment on one of my photos
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h2 class="subtitle mt-5">Comment Thread Subscriptions</h2>
|
||||
|
||||
<p class="block">
|
||||
Comment threads and forum posts may be 'subscribed' to so that you can be notified about
|
||||
comments left by other people after you. By default, you will subscribe to comment threads
|
||||
after you leave your first comment.
|
||||
</p>
|
||||
|
||||
<p class="block">
|
||||
<strong>Note:</strong> you may unsubscribe from comment threads by using the link at the
|
||||
top of its page (for example: at the top of a forum thread page or the top of the list of
|
||||
comments on a photo page). You may also opt <em>in</em> to get notifications on a thread
|
||||
that you didn't comment on by using the same link at the top of their pages.
|
||||
</p>
|
||||
|
||||
<p class="block">
|
||||
The options below can control the automatic opt-in for subscriptions when you leave a
|
||||
comment on a new comment thread.
|
||||
</p>
|
||||
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_subscriptions"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_subscriptions") "true"}}checked{{end}}>
|
||||
Subscribe to notifications for future comments when I leave a comment on something
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Unsubscribe from Comment Threads</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="unsubscribe_all_threads"
|
||||
value="true">
|
||||
Unsubscribe NOW from <strong>all ({{.SubscriptionCount}}) comment threads</strong> that I am currently following.
|
||||
</label>
|
||||
<p class="help">
|
||||
You are currently subscribed to <strong>{{.SubscriptionCount}}</strong> comment thread{{Pluralize64 .SubscriptionCount}}.
|
||||
You may immediately unsubscribe from all of these threads by checking this box and clicking "Save" below.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 class="subtitle mt-5">Miscellaneous</h2>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Notify me when...</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_friend_request_accepted"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_friend_request_accepted") "true"}}checked{{end}}>
|
||||
Somebody approves my friendship request
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
name="notif_optout_private_grant"
|
||||
value="true"
|
||||
{{if ne (.CurrentUser.GetProfileField "notif_optout_private_grant") "true"}}checked{{end}}>
|
||||
Somebody unlocks their private photos for me to see
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Read-only box for certification photo response -->
|
||||
<div class="field">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox"
|
||||
value="true"
|
||||
checked
|
||||
disabled>
|
||||
My certification photo is approved or rejected
|
||||
</label>
|
||||
<p class="help">
|
||||
This notification is important for your account status, is rarely sent out, and can
|
||||
not be opted-out from.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<button type="submit" class="button is-primary">
|
||||
<i class="fa fa-save mr-2"></i> Save Privacy Settings
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Account Settings -->
|
||||
<div id="account">
|
||||
<div class="card mb-5">
|
||||
|
@ -819,6 +1014,7 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
$prefs = document.querySelector("#prefs"),
|
||||
$location = document.querySelector("#location"),
|
||||
$privacy = document.querySelector("#privacy"),
|
||||
$notifications = document.querySelector("#notifications"),
|
||||
$account = document.querySelector("#account")
|
||||
$deactivate = document.querySelector("#deactivate"),
|
||||
buttons = Array.from(document.getElementsByClassName("nonshy-tab-button"));
|
||||
|
@ -828,6 +1024,7 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
$prefs.style.display = 'none';
|
||||
$location.style.display = 'none';
|
||||
$privacy.style.display = 'none';
|
||||
$notifications.style.display = 'none';
|
||||
$account.style.display = 'none';
|
||||
$deactivate.style.display = 'none';
|
||||
|
||||
|
@ -849,6 +1046,9 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
case "privacy":
|
||||
$activeTab = $privacy;
|
||||
break;
|
||||
case "notifications":
|
||||
$activeTab = $notifications;
|
||||
break;
|
||||
case "account":
|
||||
$activeTab = $account;
|
||||
break;
|
||||
|
@ -887,11 +1087,17 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
showTab(name);
|
||||
|
||||
e.preventDefault();
|
||||
window.requestAnimationFrame(() => {
|
||||
window.scrollTo(0, 0);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
// Show the requested tab on first page load.
|
||||
showTab(window.location.hash.replace(/^#/, ''));
|
||||
window.requestAnimationFrame(() => {
|
||||
window.scrollTo(0, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// Location tab scripts.
|
||||
|
|
Loading…
Reference in New Issue
Block a user