diff --git a/liberapay/constants.py b/liberapay/constants.py index 306e389bee..1a53ff287e 100644 --- a/liberapay/constants.py +++ b/liberapay/constants.py @@ -383,8 +383,8 @@ def __missing__(self, currency): ) PRIVACY_FIELDS = OrderedDict([ - ('hide_giving', (_("Hide total giving from others."), False)), - ('hide_receiving', (_("Hide total receiving from others."), False)), + ('hide_giving', (_("Do not publish the amounts of money I send."), False)), + ('hide_receiving', (_("Do not publish the amounts of money I receive."), False)), ('hide_from_search', (_("Hide this profile from search results on Liberapay."), True)), ('profile_noindex', (_("Tell web search engines not to index this profile."), True)), ('hide_from_lists', (_("Prevent this profile from being listed on Liberapay."), True)), diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py index ec15eeab7c..d18647d9d4 100644 --- a/liberapay/models/participant.py +++ b/liberapay/models/participant.py @@ -982,9 +982,9 @@ def clear_tips_giving(self, cursor): tippees = cursor.all(""" INSERT INTO tips ( ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, renewal_mode ) + , paid_in_advance, is_funded, renewal_mode, visibility ) SELECT ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, 0 + , paid_in_advance, is_funded, 0, visibility FROM current_tips WHERE tipper = %s AND renewal_mode > 0 @@ -1915,6 +1915,38 @@ def send_newsletters(cls): sleep(1) + # Recipient settings + # ================== + + @cached_property + def recipient_settings(self): + return self.db.one(""" + SELECT * + FROM recipient_settings + WHERE participant = %s + """, (self.id,), default=Object( + participant=self.id, + patron_visibilities=(7 if self.status == 'stub' else 0), + )) + + def update_recipient_settings(self, **kw): + cols, vals = zip(*kw.items()) + updates = ','.join('{0}=excluded.{0}'.format(col) for col in cols) + cols = ', '.join(cols) + placeholders = ', '.join(['%s']*len(vals)) + with self.db.get_cursor() as cursor: + settings = cursor.one(""" + INSERT INTO recipient_settings + (participant, {0}) + VALUES (%s, {1}) + ON CONFLICT (participant) DO UPDATE + SET {2} + RETURNING * + """.format(cols, placeholders, updates), (self.id,) + vals) + self.add_event(cursor, 'recipient_settings', kw) + self.recipient_settings = settings + + # Random Stuff # ============ @@ -2551,7 +2583,7 @@ def update_receiving(self, cursor=None): def set_tip_to(self, tippee, periodic_amount, period='weekly', renewal_mode=None, - update_self=True, update_tippee=True): + visibility=None, update_self=True, update_tippee=True): """Given a Participant or username, and amount as str, returns a dict. We INSERT instead of UPDATE, so that we have history to explore. The @@ -2599,7 +2631,8 @@ def set_tip_to(self, tippee, periodic_amount, period='weekly', renewal_mode=None INSERT INTO tips ( ctime, tipper, tippee, amount, period, periodic_amount , paid_in_advance - , renewal_mode ) + , renewal_mode + , visibility ) VALUES ( COALESCE((SELECT ctime FROM current_tip), CURRENT_TIMESTAMP) , %(tipper)s, %(tippee)s, %(amount)s, %(period)s, %(periodic_amount)s , (SELECT convert(paid_in_advance, %(currency)s) FROM current_tip) @@ -2607,12 +2640,18 @@ def set_tip_to(self, tippee, periodic_amount, period='weekly', renewal_mode=None %(renewal_mode)s, (SELECT renewal_mode FROM current_tip WHERE renewal_mode > 0), 1 + ) + , coalesce( + %(visibility)s, + (SELECT visibility FROM current_tip), + 1 ) ) RETURNING tips """, dict( tipper=self.id, tippee=tippee.id, amount=amount, currency=amount.currency, period=period, periodic_amount=periodic_amount, renewal_mode=renewal_mode, + visibility=visibility, )) t.tipper_p = self t.tippee_p = tippee @@ -2641,6 +2680,7 @@ def _zero_tip(tippee, currency=None): return Tip( amount=zero, is_funded=False, tippee=tippee.id, tippee_p=tippee, period='weekly', periodic_amount=zero, renewal_mode=0, + visibility=0, ) @@ -2648,9 +2688,9 @@ def stop_tip_to(self, tippee, update_schedule=True): t = self.db.one(""" INSERT INTO tips ( ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, renewal_mode ) + , paid_in_advance, is_funded, renewal_mode, visibility ) SELECT ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, 0 + , paid_in_advance, is_funded, 0, visibility FROM current_tips WHERE tipper = %(tipper)s AND tippee = %(tippee)s @@ -2675,14 +2715,14 @@ def hide_tip_to(self, tippee_id, hide=True): return self.db.one(""" INSERT INTO tips ( ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, renewal_mode, hidden ) + , paid_in_advance, is_funded, renewal_mode, visibility ) SELECT ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, renewal_mode, %(hide)s + , paid_in_advance, is_funded, renewal_mode, -visibility FROM current_tips WHERE tipper = %(tipper)s AND tippee = %(tippee)s AND renewal_mode = 0 - AND hidden IS NOT %(hide)s + AND (visibility < 0) IS NOT %(hide)s RETURNING tips """, dict(tipper=self.id, tippee=tippee_id, hide=hide)) @@ -3261,6 +3301,7 @@ def get_giving_details(self): , t.is_funded , t.paid_in_advance , t.renewal_mode + , t.visibility , p.payment_providers , ( t.paid_in_advance IS NULL OR t.paid_in_advance < (t.amount * 3) @@ -3269,7 +3310,7 @@ def get_giving_details(self): JOIN participants p ON p.id = t.tippee WHERE t.tipper = %s AND p.status <> 'stub' - AND t.hidden IS NOT true + AND t.visibility > 0 ORDER BY tippee, t.mtime DESC """, (self.id,)) @@ -3283,13 +3324,14 @@ def get_giving_details(self): , t.ctime , t.mtime , t.renewal_mode + , t.visibility , (e, p)::elsewhere_with_participant AS e_account FROM current_tips t JOIN participants p ON p.id = t.tippee JOIN elsewhere e ON e.participant = t.tippee WHERE t.tipper = %s AND p.status = 'stub' - AND t.hidden IS NOT true + AND t.visibility > 0 ORDER BY tippee, t.mtime DESC """, (self.id,)) @@ -3603,11 +3645,11 @@ def take_over(self, account, have_confirmation=False): -- maximum allowed. INSERT INTO tips ( ctime, tipper, tippee, amount, period - , periodic_amount, is_funded, renewal_mode, hidden + , periodic_amount, is_funded, renewal_mode, visibility , paid_in_advance ) SELECT DISTINCT ON (tipper) ctime, tipper, %(live)s AS tippee, amount, period - , periodic_amount, is_funded, renewal_mode, hidden + , periodic_amount, is_funded, renewal_mode, visibility , ( SELECT sum(t2.paid_in_advance, t.amount::currency) FROM temp_tips t2 WHERE t2.tipper = t.tipper @@ -3624,9 +3666,9 @@ def take_over(self, account, have_confirmation=False): ZERO_OUT_OLD_TIPS_RECEIVING = """ INSERT INTO tips ( ctime, tipper, tippee, amount, period, periodic_amount - , paid_in_advance, is_funded, renewal_mode, hidden ) + , paid_in_advance, is_funded, renewal_mode, visibility ) SELECT ctime, tipper, tippee, amount, period, periodic_amount - , NULL, false, 0, true + , NULL, false, 0, -visibility FROM temp_tips WHERE tippee = %(dead)s AND ( coalesce_currency_amount(paid_in_advance, amount::currency) > 0 OR @@ -3788,7 +3830,7 @@ def to_dict(self, details=False): # Key: receiving # Values: - # null - user is receiving anonymously + # null - user does not publish how much they receive # 3.00 - user receives this amount in tips if not self.hide_receiving: receiving = self.receiving @@ -3798,7 +3840,7 @@ def to_dict(self, details=False): # Key: giving # Values: - # null - user is giving anonymously + # null - user does not publish how much they give # 3.00 - user gives this amount in tips if not self.hide_giving: giving = self.giving diff --git a/liberapay/payin/common.py b/liberapay/payin/common.py index 6147bbbf56..d2e3431a8c 100644 --- a/liberapay/payin/common.py +++ b/liberapay/payin/common.py @@ -17,7 +17,7 @@ ProtoTransfer = namedtuple( 'ProtoTransfer', - 'amount recipient destination context unit_amount period team', + 'amount recipient destination context unit_amount period team visibility', ) @@ -63,7 +63,7 @@ def prepare_payin(db, payer, amount, route, proto_transfers, off_session=False): for t in proto_transfers: payin_transfers.append(prepare_payin_transfer( cursor, payin, t.recipient, t.destination, t.context, t.amount, - t.unit_amount, t.period, t.team, + t.visibility, t.unit_amount, t.period, t.team, )) return payin, payin_transfers @@ -240,8 +240,8 @@ def adjust_payin_transfers(db, payin, net_amount): unit_amount = (d.amount / n_periods).round(allow_zero=False) prepare_payin_transfer( db, payin, d.recipient, d.destination, 'team-donation', - d.amount, unit_amount, tip.period, - team=team.id + d.amount, tip.visibility, unit_amount, tip.period, + team=team.id, ) else: pt = transfers[0] @@ -303,7 +303,7 @@ def resolve_tip( ) return [ProtoTransfer( payment_amount, tippee, destination, 'personal-donation', - tip.periodic_amount, tip.period, None, + tip.periodic_amount, tip.period, None, tip.visibility, )] @@ -450,6 +450,7 @@ def resolve_team_donation( (t.resolved_amount / n_periods).round(allow_zero=False), tip.period, team.id, + tip.visibility, ) for t in selected_takes if t.resolved_amount != 0 ] @@ -460,7 +461,7 @@ def resolve_team_donation( account = payment_accounts[member.id] return [ProtoTransfer( payment_amount, member, account, 'team-donation', - tip.periodic_amount, tip.period, team.id, + tip.periodic_amount, tip.period, team.id, tip.visibility, )] @@ -571,8 +572,8 @@ def compute_priority(item): def prepare_payin_transfer( - db, payin, recipient, destination, context, amount, - unit_amount=None, period=None, team=None + db, payin, recipient, destination, context, amount, visibility, + unit_amount=None, period=None, team=None, ): """Prepare the allocation of funds from a payin. @@ -581,6 +582,7 @@ def prepare_payin_transfer( recipient (Participant): the user who will receive the money destination (Record): a row from the `payment_accounts` table amount (Money): the amount of money that will be received + visibility (int): a copy of `tip.visibility` unit_amount (Money): the `periodic_amount` of a recurrent donation period (str): the period of a recurrent payment team (int): the ID of the project this payment is tied to @@ -601,14 +603,14 @@ def prepare_payin_transfer( return db.one(""" INSERT INTO payin_transfers (payin, payer, recipient, destination, context, amount, - unit_amount, n_units, period, team, + unit_amount, n_units, period, team, visibility, status, ctime) VALUES (%s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, + %s, %s, %s, %s, %s, 'pre', clock_timestamp()) RETURNING * """, (payin.id, payin.payer, recipient.id, destination.pk, context, amount, - unit_amount, n_units, period, team)) + unit_amount, n_units, period, team, visibility)) def update_payin_transfer( diff --git a/liberapay/payin/stripe.py b/liberapay/payin/stripe.py index d63e8c2301..4ba798ca1e 100644 --- a/liberapay/payin/stripe.py +++ b/liberapay/payin/stripe.py @@ -708,9 +708,13 @@ def generate_transfer_description(pt): WHERE id = %s """, (pt.team or pt.recipient,)) if pt.team: - return f"anonymous donation for team {name} via Liberapay" + name = f"team {name}" + if pt.visibility == 3: + return f"public donation for {name} via Liberapay" + if pt.visibility == 2: + return f"private donation for {name} via Liberapay" else: - return f"anonymous donation for {name} via Liberapay" + return f"secret donation for {name} via Liberapay" def record_refunds(db, payin, charge): diff --git a/liberapay/utils/fake_data.py b/liberapay/utils/fake_data.py index d3d93ea7ef..ccb775590c 100644 --- a/liberapay/utils/fake_data.py +++ b/liberapay/utils/fake_data.py @@ -115,6 +115,7 @@ def fake_tip(db, tipper, tippee): amount=Money(amount, 'EUR'), period=period, periodic_amount=Money(periodic_amount, 'EUR'), + visibility=1, ) diff --git a/liberapay/utils/history.py b/liberapay/utils/history.py index cb4ba85e5c..c76dcb7a8c 100644 --- a/liberapay/utils/history.py +++ b/liberapay/utils/history.py @@ -471,7 +471,7 @@ def iter_payin_events(db, participant, period_start, period_end, minimize=False) outgoing_transfers = db.all(""" SELECT tr.id, tr.ctime, tr.payin, tr.recipient, tr.context, tr.status, tr.error , tr.amount, tr.fee, tr.unit_amount, tr.n_units, tr.period - , tr.reversed_amount + , tr.reversed_amount, tr.visibility , p.username AS recipient_username, p2.username AS team_name , r.network AS payin_method FROM payin_transfers tr @@ -487,7 +487,7 @@ def iter_payin_events(db, participant, period_start, period_end, minimize=False) incoming_transfers = db.all(""" SELECT tr.id, tr.ctime, tr.payin, tr.payer, tr.context, tr.status, tr.error , tr.amount, tr.fee, tr.unit_amount, tr.n_units, tr.period - , tr.reversed_amount + , tr.reversed_amount, tr.visibility , p.username AS payer_username, p2.username AS team_name , r.network AS payin_method FROM payin_transfers tr diff --git a/sql/branch.sql b/sql/branch.sql new file mode 100644 index 0000000000..0dcec600c0 --- /dev/null +++ b/sql/branch.sql @@ -0,0 +1,43 @@ +BEGIN; + ALTER TABLE tips ADD COLUMN visibility int CHECK (visibility >= -3 AND visibility <> 0 AND visibility <= 3); + -- 1 means secret, 2 means private, 3 means public, negative numbers mean hidden + ALTER TABLE payin_transfers ADD COLUMN visibility int DEFAULT 1 CHECK (visibility >= 1 AND visibility <= 3); + -- same meanings as for tips, but negative numbers aren't allowed + + UPDATE tips SET visibility = -1 WHERE hidden AND visibility IS NULL; + + CREATE OR REPLACE VIEW current_tips AS + SELECT DISTINCT ON (tipper, tippee) * + FROM tips + ORDER BY tipper, tippee, mtime DESC; + + CREATE TABLE recipient_settings + ( participant bigint PRIMARY KEY REFERENCES participants + , patron_visibilities int NOT NULL CHECK (patron_visibilities > 0) + -- Three bits: 1 is for "secret", 2 is for "private", 4 is for "public". + ); +END; + +SELECT 'after deployment'; + +BEGIN; + UPDATE tips SET visibility = -1 WHERE hidden AND visibility = 1; + DROP FUNCTION compute_arrears(current_tips); + DROP CAST (current_tips AS tips); + DROP VIEW current_tips; + ALTER TABLE tips + DROP COLUMN hidden, + ALTER COLUMN visibility DROP DEFAULT, + ALTER COLUMN visibility SET NOT NULL; + CREATE OR REPLACE VIEW current_tips AS + SELECT DISTINCT ON (tipper, tippee) * + FROM tips + ORDER BY tipper, tippee, mtime DESC; + CREATE CAST (current_tips AS tips) WITH INOUT; + CREATE FUNCTION compute_arrears(tip current_tips) RETURNS currency_amount AS $$ + SELECT compute_arrears(tip::tips); + $$ LANGUAGE sql; + ALTER TABLE payin_transfers + ALTER COLUMN visibility DROP DEFAULT, + ALTER COLUMN visibility SET NOT NULL; +END; diff --git a/style/base/base.scss b/style/base/base.scss index 7baa92c9e3..204b531735 100644 --- a/style/base/base.scss +++ b/style/base/base.scss @@ -436,6 +436,7 @@ input.search { .mini-user { display: inline-block; margin: 0 20px 25px; + text-align: center; width: 104px; .avatar-cutter-98 { border: 3px solid $gray-lighter; @@ -448,7 +449,6 @@ input.search { margin-top: 5px; max-height: 2 * $line-height-computed; overflow: hidden; - text-align: center; text-overflow: ellipsis; white-space: nowrap; } diff --git a/templates/layouts/components/navbar-logged-in.html b/templates/layouts/components/navbar-logged-in.html index 33f573074f..7abe3ccb5d 100644 --- a/templates/layouts/components/navbar-logged-in.html +++ b/templates/layouts/components/navbar-logged-in.html @@ -13,6 +13,7 @@
{{ glyphicon('info-sign') }} {{ _( + "{username} has chosen not to see who their patrons are, so your donation will be secret.", + username=tippee_name + ) }}
+ % elif patron_visibilities == 2 +{{ glyphicon('info-sign') }} {{ _( + "This donation won't be secret, you will appear in {username}'s private list of patrons.", + username=tippee_name + ) }}
+ % elif patron_visibilities == 4 +{{ glyphicon('info-sign') }} {{ _( + "{username} discloses who their patrons are, your donation will be public.", + username=tippee_name + ) }}
+ % elif patron_visibilities +{{ _("Please select a privacy level for this donation:") }}
+{{ glyphicon('info-sign') }} {{ _( + "{username} hasn't yet specified whether they want to see who their patrons are, " + "so your donation will be secret.", + username=tippee_name + ) }}
+ % endif+ % if tip.visibility == 3 + {{ fontawesome('eye') }} {{ _("Public donation") }} + % elif tip.visibility == 2 + {{ fontawesome('eye-slash') }} {{ _("Private donation") }} + % else + {{ fontawesome('user-secret') }} {{ _("Secret donation") }} + % endif + % if tip.renewal_mode == 2 % if tip.tippee_p.payment_providers == 2 - {{ glyphicon('repeat') }} {{ _( +
{{ fontawesome('repeat') }} {{ _( "Automatic renewals are enabled for this donation, but are " "currently impossible due to payment processor limitations." - ) }} + ) }}
% else - {{ glyphicon('repeat') }} {{ _("Automatic renewal") }} + {{ fontawesome('repeat') }} {{ _("Automatic renewal") }} % endif % else - {{ glyphicon('user') }} {{ _("Manual renewal") }} + {{ fontawesome('hand-pointer-o') }} {{ _("Manual renewal") }} % endif % if tippee.is_suspended @@ -320,9 +375,9 @@ next_payday = compute_next_payday_date(){{ glyphicon('exclamation-sign') }} {{ _("Awaiting payment.") }}
- - {{ glyphicon('repeat') }} {{ _("Renew") }} + {{ fontawesome('repeat') }} {{ _("Renew") }} {{ payment_methods_icons(tippee) }} % else diff --git a/www/%username/giving/pay/%payment_id.spt b/www/%username/giving/pay/%payment_id.spt index 6bfb29e7c2..6ecff71a1d 100644 --- a/www/%username/giving/pay/%payment_id.spt +++ b/www/%username/giving/pay/%payment_id.spt @@ -268,7 +268,7 @@ title = _("Funding your donations") % elif payment.auto_renewal {{ _("Doesn't support automatic renewal") }} % else - {{ _("Not anonymous") }} + {{ _("Reveals your name and email address to the recipient") }} % endif % if possible diff --git a/www/%username/giving/pay/paypal/%payin_id.spt b/www/%username/giving/pay/paypal/%payin_id.spt index 881716267f..daa801de99 100644 --- a/www/%username/giving/pay/paypal/%payin_id.spt +++ b/www/%username/giving/pay/paypal/%payin_id.spt @@ -268,8 +268,7 @@ title = _("Funding your donations") ) }}{{ _( + "Since you've chosen to make a public donation, we recommend that you " + "complete your public profile." + ) }}
+ {{ + _("Edit your profile") + }} + % endif + % if status != 'failed'{{ ngettext( + "{username} has {n} public patron.", + "{username} has {n} public patrons.", + username=participant.username, + n=n_public_patrons, + ) }}
+ +{{ ngettext( + "{username} donates publicly to {n} creator.", + "{username} donates publicly to {n} creators.", + username=participant.username, + n=n_public_donees, + ) }}
+ +{{ _( diff --git a/www/%username/ledger/index.spt b/www/%username/ledger/index.spt index d10134026a..0fdaab620c 100644 --- a/www/%username/ledger/index.spt +++ b/www/%username/ledger/index.spt @@ -16,8 +16,8 @@ participant = get_participant(state, restrict=True) title = participant.username subhead = _("Ledger") user_is_admin = user.is_acting_as('admin') -subpath = 'ledger/' if user_is_admin else '' admin_override = user_is_admin and (participant != user or 'override' in request.qs) +subpath = 'ledger/' if admin_override else '' translated_status = { None: '', 'pre': _('preparing'), @@ -179,25 +179,59 @@ if participant.join_time:
{{ ngettext( + "You have {n} active patron giving you {money_amount} per week.", + "You have {n} active patrons giving you a total of {money_amount} per week.", + p.npatrons + p.nteampatrons, money_amount=p.receiving + ) if p.receiving else _( + "You don't have any active patrons." + ) }}
+% else +{{ ngettext( + "{0} receives {1} per week from {n} patron.", + "{0} receives {1} per week from {n} patrons.", + p.npatrons + p.nteampatrons, p.username, p.receiving + ) if p.receiving else _( + "{username} doesn't have any active patrons.", + username=participant.username + ) }}
+% endif + +% set patron_visibilities = participant.recipient_settings.patron_visibilities + + +% if patron_visibilities > 1 +{{ fontawesome('download') }} {{ + _("Download the list of currently active patrons") +}}
+{{ fontawesome('download') }} {{ + _("Download the record of all patrons in the last ten years") +}}
+ +% if participant.is_person +{{ ngettext( + "{0} receives {1} per week from {n} patron.", + "{0} receives {1} per week from {n} patrons.", + team.npatrons + team.nteampatrons, + '%s'|safe % (team.path(''), team.username), + team.receiving + ) }}
+{{ + _("View the patrons of {username}", username=team.username) + }}
+ % endfor + % else +{{ _( + "You are not a member of any team." + ) if participant == user else _( + "{username} isn't a member of any team.", username=participant.username + ) }}
+ % endif +% endif +% endif + +% endblock diff --git a/www/%username/patrons/public.spt b/www/%username/patrons/public.spt new file mode 100644 index 0000000000..5889086023 --- /dev/null +++ b/www/%username/patrons/public.spt @@ -0,0 +1,34 @@ +from pando.utils import utcnow + +from liberapay.utils import get_participant + +[---] + +participant = get_participant(state, restrict=False) + +public_patrons = website.db.all(""" + SELECT tip.ctime::date AS pledge_date + , tipper_p.id AS patron_id + , tipper_p.username AS patron_username + , coalesce(tipper_p.public_name, '') AS patron_public_name + , (tip.amount).currency AS donation_currency + , ( CASE WHEN tipper_p.hide_giving THEN 'private' + ELSE (tip.amount).amount::text + END ) AS weekly_amount + , tipper_p.avatar_url AS patron_avatar_url + FROM current_tips tip + JOIN participants tipper_p ON tipper_p.id = tip.tipper + WHERE tip.tippee = %s + AND tip.visibility = 3 + AND tip.paid_in_advance > 0 + AND tip.renewal_mode > 0 + ORDER BY tip.ctime, tip.id +""", (participant.id,)) + +response.headers[b'Content-Disposition'] = ( + "attachment; filename*=UTF-8''liberapay-public-patrons-of-%s-%s.csv" % + (participant.username, utcnow().date()) +).encode('utf8') + +[---] text/csv via csv_dump +public_patrons diff --git a/www/%username/receiving/index.html.spt b/www/%username/receiving/index.html.spt index f07703d525..c88f106ad5 100644 --- a/www/%username/receiving/index.html.spt +++ b/www/%username/receiving/index.html.spt @@ -22,7 +22,7 @@ recent_donation_changes = website.db.all(""" FROM tips t WHERE t.tippee = %(p_id)s AND t.mtime > current_timestamp - interval '30 days' - AND t.hidden IS NOT true + AND t.visibility > 0 ORDER BY t.mtime DESC, t.tipper LIMIT 30 ) t diff --git a/www/%username/tip.spt b/www/%username/tip.spt index 1d3b8ba470..42a78b13de 100644 --- a/www/%username/tip.spt +++ b/www/%username/tip.spt @@ -70,7 +70,8 @@ if request.method == 'POST': else: raise response.error(400, _("The donation amount is missing.")) renewal_mode = request.body.get_int('renewal_mode', default=1, minimum=1, maximum=2) - out = tipper.set_tip_to(tippee, amount, period, renewal_mode=renewal_mode) + visibility = request.body.get_int('visibility', default=1, minimum=1, maximum=3) + out = tipper.set_tip_to(tippee, amount, period, renewal_mode=renewal_mode, visibility=visibility) if not out: raise response.error(400, _("This donation doesn't exist or has already been stopped.")) if out['renewal_mode'] == 0: diff --git a/www/about/index.spt b/www/about/index.spt index 414f11d965..d02c1945b3 100644 --- a/www/about/index.spt +++ b/www/about/index.spt @@ -11,9 +11,9 @@ title = _("Introduction"){{ _("Liberapay is a way to donate money recurrently to people whose work you appreciate.") }}
{{ _( - "Payments come with no strings attached. You don't know exactly who is " - "giving to you, and donations are capped at {0} per week per donor to " - "dampen undue influence." + "Payments come with no strings attached. By default, recipients don't " + "know who their patrons are, and donations are capped at {0} per week " + "per donor to dampen undue influence." , constants.DONATION_LIMITS[currency]['weekly'][1] ) }}
diff --git a/www/index.html.spt b/www/index.html.spt index a8444f05d7..7a19589731 100644 --- a/www/index.html.spt +++ b/www/index.html.spt @@ -344,7 +344,11 @@ recent = website.db.one(""" {{ avatar_img(p) }}