Merge branch '0.8.x' of git@gitorious.org:+laconica-developers/laconica/dev into 0.8.x

This commit is contained in:
Robin Millette 2009-06-18 06:02:54 -04:00
commit c442b400b9
45 changed files with 1899 additions and 446 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
avatar/* avatar/*
background/*
files/* files/*
file/* file/*
_darcs/* _darcs/*

View File

@ -41,7 +41,7 @@ if (!defined('LACONICA')) {
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class BlockedfromgroupAction extends Action class BlockedfromgroupAction extends GroupDesignAction
{ {
var $page = null; var $page = null;

View File

@ -1,264 +0,0 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Change user password
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Settings
* @package Laconica
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/accountsettingsaction.php';
class DesignsettingsAction extends AccountSettingsAction
{
/**
* Title of the page
*
* @return string Title of the page
*/
function title()
{
return _('Profile design');
}
/**
* Instructions for use
*
* @return instructions for use
*/
function getInstructions()
{
return _('Customize the way your profile looks with a background image and a colour palette of your choice.');
}
/**
* Content area of the page
*
* Shows a form for changing the password
*
* @return void
*/
function showContent()
{
$user = common_current_user();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_design',
'class' => 'form_settings',
'action' =>
common_local_url('designsettings')));
$this->elementStart('fieldset');
$this->hidden('token', common_session_token());
$this->elementStart('fieldset', array('id' => 'settings_design_background-image'));
$this->element('legend', null, _('Change background image'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->element('label', array('for' => 'design_background-image_file'),
_('Upload file'));
$this->element('input', array('name' => 'design_background-image_file',
'type' => 'file',
'id' => 'design_background-image_file'));
$this->element('p', 'form_guide', _('You can upload your personal background image. The maximum file size is 2Mb.'));
$this->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt()));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->element('legend', null, _('Change colours'));
$this->elementStart('ul', 'form_data');
//This is a JSON object in the DB field. Here for testing. Remove later.
$userSwatch = '{"body":{"background-color":"#F0F2F5"},
"#content":{"background-color":"#FFFFFF"},
"#aside_primary":{"background-color":"#CEE1E9"},
"html body":{"color":"#000000"},
"a":{"color":"#002E6E"}}';
//Default theme swatch -- Where should this be stored?
$defaultSwatch = array('body' => array('background-color' => '#F0F2F5'),
'#content' => array('background-color' => '#FFFFFF'),
'#aside_primary' => array('background-color' => '#CEE1E9'),
'html body' => array('color' => '#000000'),
'a' => array('color' => '#002E6E'));
$userSwatch = ($userSwatch) ? json_decode($userSwatch, true) : $defaultSwatch;
$s = 0;
$labelSwatch = array('Background',
'Content',
'Sidebar',
'Text',
'Links');
foreach($userSwatch as $propertyvalue => $value) {
$foo = array_values($value);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-'.$s), _($labelSwatch[$s]));
$this->element('input', array('name' => 'swatch-'.$s, //prefer swatch[$s] ?
'type' => 'text',
'id' => 'swatch-'.$s,
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => $foo[0]));
$this->elementEnd('li');
$s++;
}
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->element('input', array('id' => 'settings_design_reset',
'type' => 'reset',
'value' => 'Reset',
'class' => 'submit form_action-primary',
'title' => _('Reset back to default')));
$this->submit('save', _('Save'), 'submit form_action-secondary', 'save', _('Save design'));
/*TODO: Check submitted form values:
json_encode(form values)
if submitted Swatch == DefaultSwatch, don't store in DB.
else store in BD
*/
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
/**
* Handle a post
*
* Validate input and save changes. Reload the form with a success
* or error message.
*
* @return void
*/
function handlePost()
{
/*
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
$user = common_current_user();
assert(!is_null($user)); // should already be checked
// FIXME: scrub input
$newpassword = $this->arg('newpassword');
$confirm = $this->arg('confirm');
# Some validation
if (strlen($newpassword) < 6) {
$this->showForm(_('Password must be 6 or more characters.'));
return;
} else if (0 != strcmp($newpassword, $confirm)) {
$this->showForm(_('Passwords don\'t match.'));
return;
}
if ($user->password) {
$oldpassword = $this->arg('oldpassword');
if (!common_check_user($user->nickname, $oldpassword)) {
$this->showForm(_('Incorrect old password'));
return;
}
}
$original = clone($user);
$user->password = common_munge_password($newpassword, $user->id);
$val = $user->validate();
if ($val !== true) {
$this->showForm(_('Error saving user; invalid.'));
return;
}
if (!$user->update($original)) {
$this->serverError(_('Can\'t save new password.'));
return;
}
$this->showForm(_('Password saved.'), true);
*/
}
/**
* Add the Farbtastic stylesheet
*
* @return void
*/
function showStylesheets()
{
parent::showStylesheets();
$farbtasticStyle =
common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION);
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => $farbtasticStyle,
'media' => 'screen, projection, tv'));
}
/**
* Add the Farbtastic scripts
*
* @return void
*/
function showScripts()
{
parent::showScripts();
$farbtasticPack = common_path('js/farbtastic/farbtastic.js');
$farbtasticGo = common_path('js/farbtastic/farbtastic.go.js');
$this->element('script', array('type' => 'text/javascript',
'src' => $farbtasticPack));
$this->element('script', array('type' => 'text/javascript',
'src' => $farbtasticGo));
}
}

View File

@ -23,6 +23,7 @@
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca> * @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc. * @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
@ -40,14 +41,15 @@ if (!defined('LACONICA')) {
* @category Group * @category Group
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class EditgroupAction extends Action class EditgroupAction extends GroupDesignAction
{ {
var $msg; var $msg;
var $group = null;
function title() function title()
{ {

View File

@ -151,19 +151,17 @@ class GroupblockAction extends Action
function areYouSureForm() function areYouSureForm()
{ {
$id = $this->profile->id; $id = $this->profile->id;
$this->elementStart('form', array('id' => 'block-' . $id,
'method' => 'post',
'class' => 'form_settings form_entity_block',
'action' => common_local_url('groupblock')));
$this->elementStart('fieldset');
$this->hidden('token', common_session_token());
$this->element('legend', null, _('Block user'));
$this->element('p', null, $this->element('p', null,
sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '. sprintf(_('Are you sure you want to block user "%s" from the group "%s"? '.
'They will be removed from the group, unable to post, and '. 'They will be removed from the group, unable to post, and '.
'unable to subscribe to the group in the future.'), 'unable to subscribe to the group in the future.'),
$this->profile->getBestName(), $this->profile->getBestName(),
$this->group->getBestName())); $this->group->getBestName()));
$this->elementStart('form', array('id' => 'block-' . $id,
'method' => 'post',
'class' => 'block',
'action' => common_local_url('groupblock')));
$this->hidden('token', common_session_token());
$this->hidden('blockto-' . $this->profile->id, $this->hidden('blockto-' . $this->profile->id,
$this->profile->id, $this->profile->id,
'blockto'); 'blockto');
@ -175,9 +173,8 @@ class GroupblockAction extends Action
$this->hidden($k, $v); $this->hidden($k, $v);
} }
} }
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); $this->submit('no', _('No'));
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); $this->submit('yes', _('Yes'));
$this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -0,0 +1,330 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Change user password
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Settings
* @package Laconica
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR . '/lib/designsettings.php';
class GroupDesignSettingsAction extends DesignSettingsAction
{
var $group = null;
/**
* Prepare to run
*/
function prepare($args)
{
parent::prepare($args);
if (!common_config('inboxes','enabled')) {
$this->serverError(_('Inboxes must be enabled for groups to work'));
return false;
}
if (!common_logged_in()) {
$this->clientError(_('You must be logged in to edit a group.'));
return false;
}
$nickname_arg = $this->trimmed('nickname');
$nickname = common_canonical_nickname($nickname_arg);
// Permanent redirect on non-canonical nickname
if ($nickname_arg != $nickname) {
$args = array('nickname' => $nickname);
common_redirect(common_local_url('groupdesignsettings', $args), 301);
return false;
}
if (!$nickname) {
$this->clientError(_('No nickname'), 404);
return false;
}
$groupid = $this->trimmed('groupid');
if ($groupid) {
$this->group = User_group::staticGet('id', $groupid);
} else {
$this->group = User_group::staticGet('nickname', $nickname);
}
if (!$this->group) {
$this->clientError(_('No such group'), 404);
return false;
}
$cur = common_current_user();
if (!$cur->isAdmin($this->group)) {
$this->clientError(_('You must be an admin to edit the group'), 403);
return false;
}
$this->submitaction = common_local_url('groupdesignsettings',
array('nickname' => $this->group->nickname));
return true;
}
/**
* A design for this action
*
* if the group attribute has been set, returns that group's
* design.
*
* @return Design a design object to use
*/
function getDesign()
{
if (empty($this->group)) {
return null;
}
return $this->group->getDesign();
}
/**
* Title of the page
*
* @return string Title of the page
*/
function title()
{
return _('Group design');
}
/**
* Instructions for use
*
* @return instructions for use
*/
function getInstructions()
{
return _('Customize the way your group looks ' .
'with a background image and a colour palette of your choice.');
}
/**
* Override to show group nav stuff
*
* @return nothing
*/
function showLocalNav()
{
$nav = new GroupNav($this, $this->group);
$nav->show();
}
/**
* Get the design we want to edit
*
* @return Design
*/
function getWorkingDesign() {
$design = null;
if (isset($this->group)) {
$design = $this->group->getDesign();
}
if (empty($design)) {
$design = $this->defaultDesign();
}
return $design;
}
/**
* Content area of the page
*
* Shows a form for changing the design
*
* @return void
*/
function showContent()
{
$this->showDesignForm($this->getWorkingDesign());
}
/**
* Save or update the group's design settings
*
* @return void
*/
function saveDesign()
{
try {
$bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content'));
$sbcolor = new WebColor($this->trimmed('design_sidebar'));
$tcolor = new WebColor($this->trimmed('design_text'));
$lcolor = new WebColor($this->trimmed('design_links'));
} catch (WebColorException $e) {
$this->showForm($e->getMessage());
return;
}
$onoff = $this->arg('design_background-image_onoff');
$on = false;
$off = false;
$tile = false;
if ($onoff == 'on') {
$on = true;
} else {
$off = true;
}
$repeat = $this->boolean('design_background-image_repeat');
if ($repeat) {
$tile = true;
}
$design = $this->group->getDesign();
if (!empty($design)) {
// update design
$original = clone($design);
$design->backgroundcolor = $bgcolor->intValue();
$design->contentcolor = $ccolor->intValue();
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
$design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
$result = $design->update($original);
if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__);
$this->showForm(_('Couldn\'t update your design.'));
return;
}
} else {
$this->group->query('BEGIN');
// save new design
$design = new Design();
$design->backgroundcolor = $bgcolor->intValue();
$design->contentcolor = $ccolor->intValue();
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
$design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
$id = $design->insert();
if (empty($id)) {
common_log_db_error($id, 'INSERT', __FILE__);
$this->showForm(_('Unable to save your design settings!'));
return;
}
$original = clone($this->group);
$this->group->design_id = $id;
$result = $this->group->update($original);
if (empty($result)) {
common_log_db_error($original, 'UPDATE', __FILE__);
$this->showForm(_('Unable to save your design settings!'));
$this->group->query('ROLLBACK');
return;
}
$this->group->query('COMMIT');
}
$this->saveBackgroundImage($design);
$this->showForm(_('Design preferences saved.'), true);
}
/**
* Handle input and output a page (overrided)
*
* @param array $args $_REQUEST arguments
*
* @return void
*/
function handle($args)
{
parent::handle($args);
if (!common_logged_in()) {
$this->clientError(_('Not logged in.'));
return;
} else if (!common_is_real_login()) {
// Cookie theft means that automatic logins can't
// change important settings or see private info, and
// _all_ our settings are important
common_set_returnto($this->selfUrl());
$user = common_current_user();
if ($user->hasOpenID()) {
common_redirect(common_local_url('openidlogin'), 303);
} else {
common_redirect(common_local_url('login'), 303);
}
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePost();
} else {
$this->showForm();
}
}
}

View File

@ -50,7 +50,7 @@ define('MAX_ORIGINAL', 480);
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class GrouplogoAction extends Action class GrouplogoAction extends GroupDesignAction
{ {
var $mode = null; var $mode = null;
var $imagefile = null; var $imagefile = null;

View File

@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/publicgroupnav.php';
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class GroupmembersAction extends Action class GroupmembersAction extends GroupDesignAction
{ {
var $page = null; var $page = null;

View File

@ -19,7 +19,7 @@
if (!defined('LACONICA')) { exit(1); } if (!defined('LACONICA')) { exit(1); }
class InviteAction extends Action class InviteAction extends CurrentUserDesignAction
{ {
var $mode = null; var $mode = null;
var $error = null; var $error = null;

View File

@ -45,9 +45,8 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class RepliesAction extends Action class RepliesAction extends OwnerDesignAction
{ {
var $user = null;
var $page = null; var $page = null;
/** /**

View File

@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class ShowfavoritesAction extends Action class ShowfavoritesAction extends CurrentUserDesignAction
{ {
/** User we're getting the faves of */ /** User we're getting the faves of */
var $user = null; var $user = null;

View File

@ -47,10 +47,9 @@ define('MEMBERS_PER_SECTION', 27);
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class ShowgroupAction extends Action class ShowgroupAction extends GroupDesignAction
{ {
/** group we're viewing. */
var $group = null;
/** page we're viewing. */ /** page we're viewing. */
var $page = null; var $page = null;

View File

@ -0,0 +1,208 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Change user password
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Settings
* @package Laconica
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR . '/lib/designsettings.php';
class UserDesignSettingsAction extends DesignSettingsAction
{
function prepare($args)
{
parent::prepare($args);
$this->submitaction = common_local_url('userdesignsettings');
return true;
}
/**
* Title of the page
*
* @return string Title of the page
*/
function title()
{
return _('Profile design');
}
/**
* Instructions for use
*
* @return instructions for use
*/
function getInstructions()
{
return _('Customize the way your profile looks ' .
'with a background image and a colour palette of your choice.');
}
/**
* Get the design we want to edit
*
* @return Design
*/
function getWorkingDesign() {
$user = common_current_user();
$design = $user->getDesign();
if (empty($design)) {
$design = $this->defaultDesign();
}
return $design;
}
/**
* Content area of the page
*
* Shows a form for changing the design
*
* @return void
*/
function showContent()
{
$this->showDesignForm($this->getWorkingDesign());
}
/**
* Save or update the user's design settings
*
* @return void
*/
function saveDesign()
{
try {
$bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content'));
$sbcolor = new WebColor($this->trimmed('design_sidebar'));
$tcolor = new WebColor($this->trimmed('design_text'));
$lcolor = new WebColor($this->trimmed('design_links'));
} catch (WebColorException $e) {
$this->showForm($e->getMessage());
return;
}
$onoff = $this->arg('design_background-image_onoff');
$on = false;
$off = false;
$tile = false;
if ($onoff == 'on') {
$on = true;
} else {
$off = true;
}
$repeat = $this->boolean('design_background-image_repeat');
if ($repeat) {
$tile = true;
}
$user = common_current_user();
$design = $user->getDesign();
if (!empty($design)) {
$original = clone($design);
$design->backgroundcolor = $bgcolor->intValue();
$design->contentcolor = $ccolor->intValue();
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
$design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
$result = $design->update($original);
if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__);
$this->showForm(_('Couldn\'t update your design.'));
return;
}
// update design
} else {
$user->query('BEGIN');
// save new design
$design = new Design();
$design->backgroundcolor = $bgcolor->intValue();
$design->contentcolor = $ccolor->intValue();
$design->sidebarcolor = $sbcolor->intValue();
$design->textcolor = $tcolor->intValue();
$design->linkcolor = $lcolor->intValue();
$design->backgroundimage = $filepath;
$design->setDisposition($on, $off, $tile);
$id = $design->insert();
if (empty($id)) {
common_log_db_error($id, 'INSERT', __FILE__);
$this->showForm(_('Unable to save your design settings!'));
return;
}
$original = clone($user);
$user->design_id = $id;
$result = $user->update($original);
if (empty($result)) {
common_log_db_error($original, 'UPDATE', __FILE__);
$this->showForm(_('Unable to save your design settings!'));
$user->query('ROLLBACK');
return;
}
$user->query('COMMIT');
}
$this->saveBackgroundImage($design);
$this->showForm(_('Design preferences saved.'), true);
}
}

View File

@ -46,9 +46,8 @@ require_once INSTALLDIR.'/lib/grouplist.php';
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class UsergroupsAction extends Action class UsergroupsAction extends OwnerDesignAction
{ {
var $user = null;
var $page = null; var $page = null;
var $profile = null; var $profile = null;

0
background/.gitignore vendored Normal file
View File

155
classes/Design.php Normal file
View File

@ -0,0 +1,155 @@
<?php
/*
* Laconica - the distributed open-source microblogging tool
* Copyright (C) 2009, Control Yourself, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('LACONICA')) {
exit(1);
}
define('BACKGROUND_ON', 1);
define('BACKGROUND_OFF', 2);
define('BACKGROUND_TILE', 4);
/**
* Table Definition for design
*/
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
require_once INSTALLDIR . '/lib/webcolor.php';
class Design extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'design'; // table name
public $id; // int(4) primary_key not_null
public $backgroundcolor; // int(4)
public $contentcolor; // int(4)
public $sidebarcolor; // int(4)
public $textcolor; // int(4)
public $linkcolor; // int(4)
public $backgroundimage; // varchar(255)
public $disposition; // tinyint(1) default_1
/* Static get */
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Design',$k,$v); }
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
function showCSS($out)
{
try {
$bgcolor = new WebColor($this->backgroundcolor);
$ccolor = new WebColor($this->contentcolor);
$sbcolor = new WebColor($this->sidebarcolor);
$tcolor = new WebColor($this->textcolor);
$lcolor = new WebColor($this->linkcolor);
} catch (WebColorException $e) {
// This shouldn't happen
common_log(LOG_ERR, "Unable to create color for design $id.",
__FILE__);
}
$css = 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n";
$css .= '#content, #site_nav_local_views .current a { background-color: #';
$css .= $ccolor->hexValue() . '} '."\n";
$css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n";
$css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n";
$css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n";
if (!empty($this->backgroundimage) &&
$this->disposition & BACKGROUND_ON) {
$repeat = ($this->disposition & BACKGROUND_TILE) ?
'background-repeat:repeat;' :
'background-repeat:no-repeat;';
$css .= 'body { background-image:url(' .
Design::url($this->backgroundimage) .
'); ' . $repeat . ' }' . "\n";
}
$out->element('style', array('type' => 'text/css'), $css);
}
static function filename($id, $extension, $extra=null)
{
return $id . (($extra) ? ('-' . $extra) : '') . $extension;
}
static function path($filename)
{
$dir = common_config('background', 'dir');
if ($dir[strlen($dir)-1] != '/') {
$dir .= '/';
}
return $dir . $filename;
}
static function url($filename)
{
$path = common_config('background', 'path');
if ($path[strlen($path)-1] != '/') {
$path .= '/';
}
if ($path[0] != '/') {
$path = '/'.$path;
}
$server = common_config('background', 'server');
if (empty($server)) {
$server = common_config('site', 'server');
}
// XXX: protocol
return 'http://'.$server.$path.$filename;
}
function setDisposition($on, $off, $tile)
{
if ($on) {
$this->disposition |= BACKGROUND_ON;
} else {
$this->disposition &= ~BACKGROUND_ON;
}
if ($off) {
$this->disposition |= BACKGROUND_OFF;
} else {
$this->disposition &= ~BACKGROUND_OFF;
}
if ($tile) {
$this->disposition |= BACKGROUND_TILE;
} else {
$this->disposition &= ~BACKGROUND_TILE;
}
}
}

View File

@ -62,14 +62,13 @@ class User extends Memcached_DataObject
public $autosubscribe; // tinyint(1) public $autosubscribe; // tinyint(1)
public $urlshorteningservice; // varchar(50) default_ur1.ca public $urlshorteningservice; // varchar(50) default_ur1.ca
public $inboxed; // tinyint(1) public $inboxed; // tinyint(1)
public $design_id; // int(4)
public $viewdesigns; // tinyint(1) default_1
public $created; // datetime() not_null public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* Static get */ /* Static get */
function staticGet($k,$v=NULL) function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('User',$k,$v); }
{
return Memcached_DataObject::staticGet('User',$k,$v);
}
/* the code above is auto generated do not remove the tag below */ /* the code above is auto generated do not remove the tag below */
###END_AUTOCODE ###END_AUTOCODE
@ -684,4 +683,9 @@ class User extends Memcached_DataObject
return ($cnt > 0); return ($cnt > 0);
} }
function getDesign()
{
return Design::staticGet('id', $this->design_id);
}
} }

View File

@ -19,6 +19,7 @@ class User_group extends Memcached_DataObject
public $homepage_logo; // varchar(255) public $homepage_logo; // varchar(255)
public $stream_logo; // varchar(255) public $stream_logo; // varchar(255)
public $mini_logo; // varchar(255) public $mini_logo; // varchar(255)
public $design_id; // int(4)
public $created; // datetime() not_null public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
@ -239,4 +240,10 @@ class User_group extends Memcached_DataObject
} }
return null; return null;
} }
function getDesign()
{
return Design::staticGet('id', $this->design_id);
}
} }

16
classes/laconica.ini Normal file → Executable file
View File

@ -38,6 +38,19 @@ modified = 384
[consumer__keys] [consumer__keys]
consumer_key = K consumer_key = K
[design]
id = 129
backgroundcolor = 1
contentcolor = 1
sidebarcolor = 1
textcolor = 1
linkcolor = 1
backgroundimage = 2
disposition = 17
[design__keys]
id = N
[fave] [fave]
notice_id = 129 notice_id = 129
user_id = 129 user_id = 129
@ -430,6 +443,8 @@ uri = 2
autosubscribe = 17 autosubscribe = 17
urlshorteningservice = 2 urlshorteningservice = 2
inboxed = 17 inboxed = 17
design_id = 1
viewdesigns = 17
created = 142 created = 142
modified = 384 modified = 384
@ -453,6 +468,7 @@ original_logo = 2
homepage_logo = 2 homepage_logo = 2
stream_logo = 2 stream_logo = 2
mini_logo = 2 mini_logo = 2
design_id = 1
created = 142 created = 142
modified = 384 modified = 384

View File

@ -41,6 +41,7 @@ create table sms_carrier (
/* local users */ /* local users */
create table user ( create table user (
id integer primary key comment 'foreign key to profile table' references profile (id), id integer primary key comment 'foreign key to profile table' references profile (id),
nickname varchar(64) unique key comment 'nickname or username, duped in profile', nickname varchar(64) unique key comment 'nickname or username, duped in profile',
password varchar(255) comment 'salted password, can be null for OpenID users', password varchar(255) comment 'salted password, can be null for OpenID users',
@ -69,6 +70,9 @@ create table user (
autosubscribe tinyint default 0 comment 'automatically subscribe to users who subscribe to us', autosubscribe tinyint default 0 comment 'automatically subscribe to users who subscribe to us',
urlshorteningservice varchar(50) default 'ur1.ca' comment 'service to use for auto-shortening URLs', urlshorteningservice varchar(50) default 'ur1.ca' comment 'service to use for auto-shortening URLs',
inboxed tinyint default 0 comment 'has an inbox been created for this user?', inboxed tinyint default 0 comment 'has an inbox been created for this user?',
design_id integer comment 'id of a design' references design(id),
viewdesigns tinyint default 1 comment 'whether to view user-provided designs',
created datetime not null comment 'date this record was created', created datetime not null comment 'date this record was created',
modified timestamp comment 'date this record was modified', modified timestamp comment 'date this record was modified',
@ -383,6 +387,7 @@ create table user_group (
homepage_logo varchar(255) comment 'homepage (profile) size logo', homepage_logo varchar(255) comment 'homepage (profile) size logo',
stream_logo varchar(255) comment 'stream-sized logo', stream_logo varchar(255) comment 'stream-sized logo',
mini_logo varchar(255) comment 'mini logo', mini_logo varchar(255) comment 'mini logo',
design_id integer comment 'id of a design' references design(id),
created datetime not null comment 'date this record was created', created datetime not null comment 'date this record was created',
modified timestamp comment 'date this record was modified', modified timestamp comment 'date this record was modified',
@ -484,6 +489,17 @@ create table file_to_post (
unique(file_id, post_id) unique(file_id, post_id)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table design (
id integer primary key auto_increment comment 'design ID',
backgroundcolor integer comment 'main background color',
contentcolor integer comment 'content area background color',
sidebarcolor integer comment 'sidebar background color',
textcolor integer comment 'text color',
linkcolor integer comment 'link color',
backgroundimage varchar(255) comment 'background image, if any',
disposition tinyint default 1 comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image'
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table group_block ( create table group_block (
group_id integer not null comment 'group profile is blocked from' references user_group (id), group_id integer not null comment 'group profile is blocked from' references user_group (id),
blocked integer not null comment 'profile that is blocked' references profile (id), blocked integer not null comment 'profile that is blocked' references profile (id),

View File

@ -1,5 +1,21 @@
// $Id: farbtastic.js,v 1.2 2007/01/08 22:53:01 unconed Exp $ /**
// Farbtastic 1.2 * Farbtastic Color Picker 1.2
* © 2008 Steven Wittens
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
jQuery.fn.farbtastic = function (callback) { jQuery.fn.farbtastic = function (callback) {
$.farbtastic(this, callback); $.farbtastic(this, callback);

View File

@ -10,19 +10,19 @@ $(document).ready(function() {
function UpdateColors(S) { function UpdateColors(S) {
C = $(S).val(); C = $(S).val();
switch (parseInt(S.id.slice(-1))) { switch (parseInt(S.id.slice(-1))) {
case 0: default: case 1: default:
$('body').css({'background-color':C}); $('html, body').css({'background-color':C});
break;
case 1:
$('#content').css({'background-color':C});
break; break;
case 2: case 2:
$('#aside_primary').css({'background-color':C}); $('#content, #site_nav_local_views .current a').css({'background-color':C});
break; break;
case 3: case 3:
$('body').css({'color':C}); $('#aside_primary').css({'background-color':C});
break; break;
case 4: case 4:
$('html body').css({'color':C});
break;
case 5:
$('a').css({'color':C}); $('a').css({'color':C});
break; break;
} }
@ -49,7 +49,7 @@ $(document).ready(function() {
} }
} }
function Init() { function InitFarbtastic() {
$('#settings_design_color').append('<div id="color-picker"></div>'); $('#settings_design_color').append('<div id="color-picker"></div>');
$('#color-picker').hide(); $('#color-picker').hide();
@ -59,7 +59,9 @@ $(document).ready(function() {
swatches swatches
.each(SynchColors) .each(SynchColors)
.blur(function() { .blur(function() {
$(this).val($(this).val().toUpperCase()); tv = $(this).val();
$(this).val(tv.toUpperCase());
(tv.length == 4) ? ((tv[0] == '#') ? $(this).val('#'+tv[1]+tv[1]+tv[2]+tv[2]+tv[3]+tv[3]) : '') : '';
}) })
.focus(function() { .focus(function() {
$('#color-picker').show(); $('#color-picker').show();
@ -73,13 +75,25 @@ $(document).ready(function() {
} }
var f, swatches; var f, swatches;
Init(); InitFarbtastic();
$('#form_settings_design').bind('reset', function(){ $('#form_settings_design').bind('reset', function(){
setTimeout(function(){ setTimeout(function(){
swatches.each(function(){UpdateColors(this);}); swatches.each(function(){UpdateColors(this);});
$('#color-picker').remove(); $('#color-picker').remove();
swatches.unbind(); swatches.unbind();
Init(); InitFarbtastic();
},10); },10);
}); });
});
$('#design_background-image_off').focus(function() {
$('body').css({'background-image':'none'});
});
$('#design_background-image_on').focus(function() {
var bis = $('#design_background-image_onoff img')[0].src;
$('body').css({'background-image':'url('+bis+')'});
});
$('#design_background-image_repeat').click(function() {
($(this)[0].checked) ? $('body').css({'background-repeat':'repeat'}) : $('body').css({'background-repeat':'no-repeat'});
});
});

View File

@ -235,7 +235,7 @@ $(document).ready(function(){
}); });
function NoticeReply() { function NoticeReply() {
if ($('#notice_data-text').length > 0) { if ($('#notice_data-text').length > 0 && $('#content .notice_reply').length > 0) {
$('#content .notice').each(function() { $('#content .notice').each(function() {
var notice = $(this)[0]; var notice = $(this)[0];
$($('.notice_reply', notice)[0]).click(function() { $($('.notice_reply', notice)[0]).click(function() {
@ -308,4 +308,4 @@ function NoticeAttachments() {
$(this).closest(".entry-title").removeClass('ov'); $(this).closest(".entry-title").removeClass('ov');
} }
); );
} }

View File

@ -115,7 +115,7 @@ class AccountSettingsNav extends Widget
'openidsettings' => 'openidsettings' =>
array(_('OpenID'), array(_('OpenID'),
_('Add or remove OpenIDs')), _('Add or remove OpenIDs')),
'designsettings' => 'userdesignsettings' =>
array(_('Design'), array(_('Design'),
_('Design your profile')), _('Design your profile')),
'othersettings' => 'othersettings' =>

View File

@ -46,7 +46,6 @@ if (!defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
* @see Notice * @see Notice
* @see StreamAction
* @see NoticeListItem * @see NoticeListItem
* @see ProfileNoticeList * @see ProfileNoticeList
*/ */

View File

@ -71,6 +71,15 @@ $config =
array('name' => 'Just another Laconica microblog', array('name' => 'Just another Laconica microblog',
'server' => $_server, 'server' => $_server,
'theme' => 'default', 'theme' => 'default',
'skin' => 'default',
'design' =>
array('backgroundcolor' => '#F0F2F5',
'contentcolor' => '#FFFFFF',
'sidebarcolor' => '#CEE1E9',
'textcolor' => '#000000',
'linkcolor' => '#002E6E',
'backgroundimage' => null,
'disposition' => 1),
'path' => $_path, 'path' => $_path,
'logfile' => null, 'logfile' => null,
'logo' => null, 'logo' => null,
@ -111,6 +120,10 @@ $config =
array('server' => null, array('server' => null,
'dir' => INSTALLDIR . '/avatar/', 'dir' => INSTALLDIR . '/avatar/',
'path' => $_path . '/avatar/'), 'path' => $_path . '/avatar/'),
'background' =>
array('server' => null,
'dir' => INSTALLDIR . '/background/',
'path' => $_path . '/background/'),
'public' => 'public' =>
array('localonly' => true, array('localonly' => true,
'blacklist' => array(), 'blacklist' => array(),

View File

@ -2,7 +2,7 @@
/** /**
* Laconica, the distributed open-source microblogging tool * Laconica, the distributed open-source microblogging tool
* *
* User profile page * Base class for actions that use the current user's design
* *
* PHP version 5 * PHP version 5
* *
@ -19,11 +19,10 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* @category Personal * @category Action
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca> * @copyright 2009 Control Yourself, Inc.
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
@ -33,28 +32,57 @@ if (!defined('LACONICA')) {
} }
/** /**
* Base class for user profile page * Base class for actions that use the current user's design
* *
* @category Personal * Some pages (settings in particular) use the current user's chosen
* design. This superclass returns that design.
*
* @category Action
* @package Laconica * @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca> * @author Evan Prodromou <evan@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
*
*/ */
class PersonalAction extends Action class CurrentUserDesignAction extends Action
{ {
var $user = null; /**
* Show the user's design stylesheet
*
* @return nothing
*/
function showStylesheets()
{
parent::showStylesheets();
function isReadOnly($args) $design = $this->getDesign();
if (!empty($design)) {
$design->showCSS($this);
}
}
/**
* A design for this action
*
* if the user attribute has been set, returns that user's
* design.
*
* @return Design a design object to use
*/
function getDesign()
{ {
return true; $cur = common_current_user();
if (empty($cur)) {
return null;
}
return $cur->getDesign();
} }
function handle($args)
{
parent::handle($args);
}
} }

402
lib/designsettings.php Normal file
View File

@ -0,0 +1,402 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Change user password
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Settings
* @package Laconica
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR . '/lib/accountsettingsaction.php';
require_once INSTALLDIR . '/lib/webcolor.php';
class DesignSettingsAction extends AccountSettingsAction
{
var $submitaction = null;
/**
* Title of the page
*
* @return string Title of the page
*/
function title()
{
return _('Profile design');
}
/**
* Instructions for use
*
* @return instructions for use
*/
function getInstructions()
{
return _('Customize the way your profile looks ' .
'with a background image and a colour palette of your choice.');
}
function showDesignForm($design)
{
$this->elementStart('form', array('method' => 'post',
'enctype' => 'multipart/form-data',
'id' => 'form_settings_design',
'class' => 'form_settings',
'action' => $this->submitaction));
$this->elementStart('fieldset');
$this->hidden('token', common_session_token());
$this->elementStart('fieldset', array('id' =>
'settings_design_background-image'));
$this->element('legend', null, _('Change background image'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->element('label', array('for' => 'design_background-image_file'),
_('Upload file'));
$this->element('input', array('name' => 'design_background-image_file',
'type' => 'file',
'id' => 'design_background-image_file'));
$this->element('p', 'form_guide', _('You can upload your personal ' .
'background image. The maximum file size is 2Mb.'));
$this->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => ImageFile::maxFileSizeInt()));
$this->elementEnd('li');
if (!empty($design->backgroundimage)) {
$this->elementStart('li', array('id' => 'design_background-image_onoff'));
$this->element('img', array('src' =>
Design::url($design->backgroundimage)));
$attrs = array('name' => 'design_background-image_onoff',
'type' => 'radio',
'id' => 'design_background-image_on',
'class' => 'radio',
'value' => 'on');
if ($design->disposition & BACKGROUND_ON) {
$attrs['checked'] = 'checked';
}
$this->element('input', $attrs);
$this->element('label', array('for' => 'design_background-image_on',
'class' => 'radio'),
_('On'));
$attrs = array('name' => 'design_background-image_onoff',
'type' => 'radio',
'id' => 'design_background-image_off',
'class' => 'radio',
'value' => 'off');
if ($design->disposition & BACKGROUND_OFF) {
$attrs['checked'] = 'checked';
}
$this->element('input', $attrs);
$this->element('label', array('for' => 'design_background-image_off',
'class' => 'radio'),
_('Off'));
$this->element('p', 'form_guide', _('Turn background image on or off.'));
$this->elementEnd('li');
}
$this->elementStart('li');
$this->checkbox('design_background-image_repeat',
_('Tile background image'),
($design->disposition & BACKGROUND_TILE) ? true : false );
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->element('legend', null, _('Change colours'));
$this->elementStart('ul', 'form_data');
try {
$bgcolor = new WebColor($design->backgroundcolor);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-1'), _('Background'));
$this->element('input', array('name' => 'design_background',
'type' => 'text',
'id' => 'swatch-1',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => '#' . $bgcolor->hexValue()));
$this->elementEnd('li');
$ccolor = new WebColor($design->contentcolor);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-2'), _('Content'));
$this->element('input', array('name' => 'design_content',
'type' => 'text',
'id' => 'swatch-2',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => '#' . $ccolor->hexValue()));
$this->elementEnd('li');
$sbcolor = new WebColor($design->sidebarcolor);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-3'), _('Sidebar'));
$this->element('input', array('name' => 'design_sidebar',
'type' => 'text',
'id' => 'swatch-3',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => '#' . $sbcolor->hexValue()));
$this->elementEnd('li');
$tcolor = new WebColor($design->textcolor);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-4'), _('Text'));
$this->element('input', array('name' => 'design_text',
'type' => 'text',
'id' => 'swatch-4',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => '#' . $tcolor->hexValue()));
$this->elementEnd('li');
$lcolor = new WebColor($design->linkcolor);
$this->elementStart('li');
$this->element('label', array('for' => 'swatch-5'), _('Links'));
$this->element('input', array('name' => 'design_links',
'type' => 'text',
'id' => 'swatch-5',
'class' => 'swatch',
'maxlength' => '7',
'size' => '7',
'value' => '#' . $lcolor->hexValue()));
$this->elementEnd('li');
} catch (WebColorException $e) {
common_log(LOG_ERR, 'Bad color values in design ID: ' .
$design->id);
}
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->element('input', array('id' => 'settings_design_reset',
'type' => 'reset',
'value' => 'Reset',
'class' => 'submit form_action-primary',
'title' => _('Reset back to default')));
$this->submit('save', _('Save'), 'submit form_action-secondary',
'save', _('Save design'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
/**
* Handle a post
*
* Validate input and save changes. Reload the form with a success
* or error message.
*
* @return void
*/
function handlePost()
{
// XXX: Robin's workaround for a bug in PHP where $_POST
// and $_FILE are empty in the case that the uploaded
// file is bigger than PHP is configured to handle.
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) {
$msg = _('The server was unable to handle that much POST ' .
'data (%s bytes) due to its current configuration.');
$this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
}
}
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if ($this->arg('save')) {
$this->saveDesign();
} else if ($this->arg('reset')) {
$this->resetDesign();
} else {
$this->showForm(_('Unexpected form submission.'));
}
}
/**
* Add the Farbtastic stylesheet
*
* @return void
*/
function showStylesheets()
{
parent::showStylesheets();
$farbtasticStyle =
common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION);
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => $farbtasticStyle,
'media' => 'screen, projection, tv'));
}
/**
* Add the Farbtastic scripts
*
* @return void
*/
function showScripts()
{
parent::showScripts();
$farbtasticPack = common_path('js/farbtastic/farbtastic.js');
$userDesignGo = common_path('js/userdesign.go.js');
$this->element('script', array('type' => 'text/javascript',
'src' => $farbtasticPack));
$this->element('script', array('type' => 'text/javascript',
'src' => $userDesignGo));
}
/**
* Get a default user design
*
* @return Design design
*/
function defaultDesign()
{
$defaults = common_config('site', 'design');
$design = new Design();
try {
$color = new WebColor();
$color->parseColor($defaults['backgroundcolor']);
$design->backgroundcolor = $color->intValue();
$color->parseColor($defaults['contentcolor']);
$design->contentcolor = $color->intValue();
$color->parseColor($defaults['sidebarcolor']);
$design->sidebarcolor = $color->intValue();
$color->parseColor($defaults['textcolor']);
$design->textcolor = $color->intValue();
$color->parseColor($defaults['linkcolor']);
$design->linkcolor = $color->intValue();
$design->backgroundimage = $defaults['backgroundimage'];
$design->disposition = $defaults['disposition'];
} catch (WebColorException $e) {
common_log(LOG_ERR, _('Bad default color settings: ' .
$e->getMessage()));
}
return $design;
}
function saveBackgroundImage($design) {
// Now that we have a Design ID we can add a file to the design.
// XXX: This is an additional DB hit, but figured having the image
// associated with the Design rather than the User was worth
// it. -- Zach
if ($_FILES['design_background-image_file']['error'] ==
UPLOAD_ERR_OK) {
$filepath = null;
try {
$imagefile =
ImageFile::fromUpload('design_background-image_file');
} catch (Exception $e) {
$this->showForm($e->getMessage());
return;
}
$filename = Design::filename($design->id,
image_type_to_extension($imagefile->type),
common_timestamp());
$filepath = Design::path($filename);
move_uploaded_file($imagefile->filepath, $filepath);
$original = clone($design);
$design->backgroundimage = $filename;
$design->setDisposition(true, false, false);
$result = $design->update($original);
if ($result === false) {
common_log_db_error($design, 'UPDATE', __FILE__);
$this->showForm(_('Couldn\'t update your design.'));
return;
}
}
}
}

View File

@ -27,10 +27,9 @@ require_once INSTALLDIR.'/lib/profilelist.php';
define('AVATARS_PER_PAGE', 80); define('AVATARS_PER_PAGE', 80);
class GalleryAction extends Action class GalleryAction extends OwnerDesignAction
{ {
var $profile = null; var $profile = null;
var $user = null;
var $page = null; var $page = null;
var $tag = null; var $tag = null;

87
lib/groupdesignaction.php Normal file
View File

@ -0,0 +1,87 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Base class for actions that use the current user's design
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Action
* @package Laconica
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
/**
* Base class for actions that use a group's design
*
* Pages related to groups can be themed with a design.
* This superclass returns that design.
*
* @category Action
* @package Laconica
* @author Zach Copley <zach@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*
*/
class GroupDesignAction extends Action {
/** The group in question */
var $group = null;
/**
* Show the groups's design stylesheet
*
* @return nothing
*/
function showStylesheets()
{
parent::showStylesheets();
$design = $this->getDesign();
if (!empty($design)) {
$design->showCSS($this);
}
}
/**
* A design for this action
*
* if the group attribute has been set, returns that group's
* design.
*
* @return Design a design object to use
*/
function getDesign()
{
if (empty($this->group)) {
return null;
}
return $this->group->getDesign();
}
}

View File

@ -113,6 +113,12 @@ class GroupNav extends Widget
sprintf(_('Add or edit %s logo'), $nickname), sprintf(_('Add or edit %s logo'), $nickname),
$action_name == 'grouplogo', $action_name == 'grouplogo',
'nav_group_logo'); 'nav_group_logo');
$this->out->menuItem(common_local_url('groupdesignsettings', array('nickname' =>
$nickname)),
_('Design'),
sprintf(_('Add or edit %s design'), $nickname),
$action_name == 'groupdesignsettings',
'nav_group_design');
} }
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
} }

View File

@ -31,8 +31,6 @@ if (!defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/personal.php';
define('MESSAGES_PER_PAGE', 20); define('MESSAGES_PER_PAGE', 20);
/** /**
@ -47,11 +45,11 @@ define('MESSAGES_PER_PAGE', 20);
* @see OutboxAction * @see OutboxAction
*/ */
class MailboxAction extends PersonalAction class MailboxAction extends CurrentUserDesignAction
{ {
var $page = null; var $page = null;
function prepare($args) function prepare($args)
{ {
parent::prepare($args); parent::prepare($args);
@ -265,12 +263,12 @@ class MailboxAction extends PersonalAction
* Returns either the name (and link) of the API client that posted the notice, * Returns either the name (and link) of the API client that posted the notice,
* or one of other other channels. * or one of other other channels.
* *
* @param string $source the source of the message * @param string $source the source of the message
* *
* @return void * @return void
*/ */
function showSource($source) function showSource($source)
{ {
$source_name = _($source); $source_name = _($source);
switch ($source) { switch ($source) {
@ -297,4 +295,17 @@ class MailboxAction extends PersonalAction
return; return;
} }
/**
* Mailbox actions are read only
*
* @param array $args other arguments
*
* @return boolean
*/
function isReadOnly($args)
{
return true;
}
} }

View File

@ -50,7 +50,6 @@ require_once INSTALLDIR.'/lib/attachmentlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/ * @link http://laconi.ca/
* @see Notice * @see Notice
* @see StreamAction
* @see NoticeListItem * @see NoticeListItem
* @see ProfileNoticeList * @see ProfileNoticeList
*/ */

88
lib/ownerdesignaction.php Normal file
View File

@ -0,0 +1,88 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Base class for actions that use the page owner's design
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Action
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @copyright 2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
/**
* Base class for actions that use the page owner's design
*
* Some pages have a clear "owner" -- like the profile page, subscriptions
* pages, etc. This superclass uses that owner's chosen design for the page
* design.
*
* @category Action
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*
*/
class OwnerDesignAction extends Action {
/** The user for this page. */
var $user = null;
/**
* Show the owner's design stylesheet
*
* @return nothing
*/
function showStylesheets()
{
parent::showStylesheets();
$design = $this->getDesign();
if (!empty($design)) {
$design->showCSS($this);
}
}
/**
* A design for this action
*
* if the user attribute has been set, returns that user's
* design.
*
* @return Design a design object to use
*/
function getDesign()
{
if (empty($this->user)) {
return null;
}
return $this->user->getDesign();
}
}

View File

@ -47,9 +47,8 @@ require_once INSTALLDIR.'/lib/groupminilist.php';
* @link http://laconi.ca/ * @link http://laconi.ca/
*/ */
class ProfileAction extends Action class ProfileAction extends OwnerDesignAction
{ {
var $user = null;
var $page = null; var $page = null;
var $profile = null; var $profile = null;
var $tag = null; var $tag = null;

View File

@ -132,7 +132,7 @@ class Router
// settings // settings
foreach (array('profile', 'avatar', 'password', 'openid', 'im', foreach (array('profile', 'avatar', 'password', 'openid', 'im',
'email', 'sms', 'twitter', 'design', 'other') as $s) { 'email', 'sms', 'twitter', 'userdesign', 'other') as $s) {
$m->connect('settings/'.$s, array('action' => $s.'settings')); $m->connect('settings/'.$s, array('action' => $s.'settings'));
} }
@ -223,7 +223,7 @@ class Router
array('nickname' => '[a-zA-Z0-9]+')); array('nickname' => '[a-zA-Z0-9]+'));
} }
foreach (array('members', 'logo', 'rss') as $n) { foreach (array('members', 'logo', 'rss', 'designsettings') as $n) {
$m->connect('group/:nickname/'.$n, $m->connect('group/:nickname/'.$n,
array('action' => 'group'.$n), array('action' => 'group'.$n),
array('nickname' => '[a-zA-Z0-9]+')); array('nickname' => '[a-zA-Z0-9]+'));

View File

@ -43,7 +43,7 @@ if (!defined('LACONICA')) {
* @see Widget * @see Widget
*/ */
class SettingsAction extends Action class SettingsAction extends CurrentUserDesignAction
{ {
/** /**
* A message for the user. * A message for the user.

View File

@ -1,32 +0,0 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, Controlez-Vous, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/personal.php');
require_once(INSTALLDIR.'/lib/noticelist.php');
class StreamAction extends PersonalAction
{
function show_notice_list($notice)
{
$nl = new NoticeList($notice);
return $nl->show();
}
}

192
lib/webcolor.php Normal file
View File

@ -0,0 +1,192 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Base class for deleting things
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Personal
* @package Laconica
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2009 Control Yourself, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
class WebColor {
// XXX: Maybe make getters and setters for r,g,b values and tuples,
// e.g.: to support this kinda CSS representation: rgb(255,0,0)
// http://www.w3.org/TR/CSS21/syndata.html#color-units
var $red = 0;
var $green = 0;
var $blue = 0;
/**
* Constructor
*
* @return nothing
*/
function __construct($color = null)
{
if (isset($color)) {
$this->parseColor($color);
}
}
/**
* Parses input to and tries to determine whether the color
* is being specified via an integer or hex tuple and sets
* the RGB instance variables accordingly.
*
* XXX: Maybe support (r,g,b) style, and array?
*
* @param mixed $color
*
* @return nothing
*/
function parseColor($color) {
if (is_numeric($color)) {
$this->setIntColor($color);
} else {
// XXX named colors
// XXX: probably should do even more validation
if (preg_match('/(#([0-9A-Fa-f]{3,6})\b)/u', $color) > 0) {
$this->setHexColor($color);
} else {
$errmsg = _('%s is not a valid color!');
throw new WebColorException(sprintf($errmsg, $color));
}
}
}
/**
* @param string $name
*
* @return nothing
*/
function setNamedColor($name)
{
// XXX Implement this
}
/**
* Sets the RGB color values from a a hex tuple
*
* @param string $hexcolor
*
* @return nothing
*/
function setHexColor($hexcolor) {
if ($hexcolor[0] == '#') {
$hexcolor = substr($hexcolor, 1);
}
if (strlen($hexcolor) == 6) {
list($r, $g, $b) = array($hexcolor[0].$hexcolor[1],
$hexcolor[2].$hexcolor[3],
$hexcolor[4].$hexcolor[5]);
} elseif (strlen($hexcolor) == 3) {
list($r, $g, $b) = array($hexcolor[0].$hexcolor[0],
$hexcolor[1].$hexcolor[1],
$hexcolor[2].$hexcolor[2]);
} else {
$errmsg = _('%s is not a valid color! Use 3 or 6 hex chars.');
throw new WebColorException(sprintf($errmsg, $hexcolor));
}
$this->red = hexdec($r);
$this->green = hexdec($g);
$this->blue = hexdec($b);
}
/**
* Sets the RGB color values from a 24-bit integer
*
* @param int $intcolor
*
* @return nothing
*/
function setIntColor($intcolor)
{
// We could do 32 bit and have an alpha channel because
// Sarven wants one real bad, but nah.
$this->red = $intcolor >> 16;
$this->green = $intcolor >> 8 & 0xFF;
$this->blue = $intcolor & 0xFF;
}
/**
* Returns a hex tuple of the RGB color useful for output in HTML
*
* @return string
*/
function hexValue() {
$hexcolor = (strlen(dechex($this->red)) < 2 ? '0' : '' ) .
dechex($this->red);
$hexcolor .= (strlen(dechex($this->green)) < 2 ? '0' : '') .
dechex($this->green);
$hexcolor .= (strlen(dechex($this->blue)) < 2 ? '0' : '') .
dechex($this->blue);
return strtoupper($hexcolor);
}
/**
* Returns a 24-bit packed integer representation of the RGB color
* for convenient storage in the DB
*
* XXX: probably could just use hexdec() instead
*
* @return int
*/
function intValue()
{
$intcolor = 256 * 256 * $this->red + 256 * $this->green + $this->blue;
return $intcolor;
}
}
class WebColorException extends Exception
{
}
?>

View File

@ -12,9 +12,9 @@ img { display:block; border:0; }
a abbr { cursor: pointer; border-bottom:0; } a abbr { cursor: pointer; border-bottom:0; }
table { border-collapse:collapse; } table { border-collapse:collapse; }
ol { list-style-position:inside; } ol { list-style-position:inside; }
html { font-size: 87.5%; background-color:#fff; height:100%; } html { font-size: 87.5%; }
body { body {
background-color:#fff; background-color:#FFFFFF;
color:#000; color:#000;
font-family:sans-serif; font-family:sans-serif;
font-size:1em; font-size:1em;
@ -77,7 +77,8 @@ margin:0 0 18px 0;
form label { form label {
font-weight:bold; font-weight:bold;
} }
input.checkbox { input.checkbox,
input.radio {
position:relative; position:relative;
top:2px; top:2px;
left:0; left:0;
@ -169,7 +170,8 @@ margin-bottom:0;
margin-bottom:11px; margin-bottom:11px;
} }
.form_settings input.checkbox { .form_settings input.checkbox,
.form_settings input.radio {
margin-top:3px; margin-top:3px;
margin-left:0; margin-left:0;
} }
@ -181,13 +183,19 @@ margin-left:11px;
float:left; float:left;
width:90%; width:90%;
} }
.form_settings label.radio {
margin-top:0;
margin-right:47px;
margin-left:11px;
width:auto;
}
#form_login p.form_guide, #form_login p.form_guide,
#form_register #settings_rememberme p.form_guide, #form_register #settings_rememberme p.form_guide,
#form_openid_login #settings_rememberme p.form_guide, #form_openid_login #settings_rememberme p.form_guide,
#settings_twitter_remove p.form_guide, #settings_twitter_remove p.form_guide,
#form_search ul.form_data #q { #form_search ul.form_data #q,
#design_background-image_onoff p.form_guide {
margin-left:0; margin-left:0;
} }

View File

@ -1,8 +1,6 @@
/* IE specific styles */ /* IE specific styles */
legend { input.checkbox,
margin-left:-7px; input.radio {
}
input.checkbox {
top:0; top:0;
} }
#form_notice textarea { #form_notice textarea {

View File

@ -9,7 +9,6 @@
@import url(../../base/css/display.css); @import url(../../base/css/display.css);
html,
body, body,
a:active { a:active {
background-color:#C3D6DF; background-color:#C3D6DF;
@ -245,7 +244,7 @@ div.notice-options a,
div.notice-options input { div.notice-options input {
font-family:sans-serif; font-family:sans-serif;
} }
.notices li:hover { #content .notices li:hover {
background-color:#FCFCFC; background-color:#FCFCFC;
} }
#conversation .notices li:hover { #conversation .notices li:hover {

View File

@ -9,7 +9,6 @@
@import url(../../base/css/display.css); @import url(../../base/css/display.css);
html,
body, body,
a:active { a:active {
background-color:#F0F2F5; background-color:#F0F2F5;
@ -245,7 +244,7 @@ div.notice-options a,
div.notice-options input { div.notice-options input {
font-family:sans-serif; font-family:sans-serif;
} }
.notices li:hover { #content .notices li:hover {
background-color:#FCFCFC; background-color:#FCFCFC;
} }
#conversation .notices li:hover { #conversation .notices li:hover {

View File

@ -12,9 +12,9 @@ img { display:block; border:0; }
a abbr { cursor: pointer; border-bottom:0; } a abbr { cursor: pointer; border-bottom:0; }
table { border-collapse:collapse; } table { border-collapse:collapse; }
ol { list-style-position:inside; } ol { list-style-position:inside; }
html { font-size: 87.5%; background-color:#fff; } html { font-size: 87.5%; }
body { body {
background-color:#fff; background-color:#FFFFFF;
color:#000; color:#000;
font-family:sans-serif; font-family:sans-serif;
font-size:1em; font-size:1em;
@ -78,7 +78,8 @@ margin:0 0 18px 0;
form label { form label {
font-weight:bold; font-weight:bold;
} }
input.checkbox { input.checkbox,
input.radio {
position:relative; position:relative;
top:2px; top:2px;
left:0; left:0;
@ -155,7 +156,8 @@ font-weight:bold;
#form_invite legend, #form_invite legend,
#form_notice_delete legend, #form_notice_delete legend,
#form_password_recover legend, #form_password_recover legend,
#form_password_change legend { #form_password_change legend,
.form_entity_block legend {
display:none; display:none;
} }
@ -181,13 +183,19 @@ margin-left:11px;
float:left; float:left;
width:90%; width:90%;
} }
.form_settings label.radio {
margin-top:0;
margin-right:47px;
margin-left:11px;
width:auto;
}
#form_login p.form_guide, #form_login p.form_guide,
#form_register #settings_rememberme p.form_guide, #form_register #settings_rememberme p.form_guide,
#form_openid_login #settings_rememberme p.form_guide, #form_openid_login #settings_rememberme p.form_guide,
#settings_twitter_remove p.form_guide, #settings_twitter_remove p.form_guide,
#form_search ul.form_data #q { #form_search ul.form_data #q,
#design_background-image_onoff p.form_guide {
margin-left:0; margin-left:0;
} }
@ -375,10 +383,10 @@ margin-bottom:1em;
} }
#content { #content {
width:50.009%; width:49.009%;
min-height:259px; min-height:259px;
float:left; float:left;
margin-left:18px; padding:0 18px;
} }
#shownotice #content { #shownotice #content {
min-height:0; min-height:0;
@ -421,6 +429,8 @@ width:80.789%;
height:46px; height:46px;
line-height:1.5; line-height:1.5;
padding:7px 7px 16px 7px; padding:7px 7px 16px 7px;
position:relative;
z-index:2;
} }
#form_notice label { #form_notice label {
display:block; display:block;
@ -428,8 +438,22 @@ float:left;
font-size:1.3em; font-size:1.3em;
margin-bottom:7px; margin-bottom:7px;
} }
#form_notice #notice_submit label { #form_notice label[for=notice_data-attach],
display:none; #form_notice #notice_data-attach {
position:absolute;
top:25px;
cursor:pointer;
}
#form_notice label[for=notice_data-attach] {
text-indent:-9999px;
left:394px;
width:16px;
height:16px;
}
#form_notice #notice_data-attach {
left:183px;
padding:0;
height:16px;
} }
#form_notice .form_note { #form_notice .form_note {
position:absolute; position:absolute;
@ -509,12 +533,15 @@ margin-bottom:4px;
.entity_profile .entity_nickname { .entity_profile .entity_nickname {
margin-left:11px; margin-left:11px;
display:inline; display:inline;
font-weight:bold;
} }
.entity_profile .entity_nickname { .entity_profile .entity_nickname {
margin-left:0; margin-left:0;
} }
.entity_profile .fn,
.entity_profile .nickname {
font-size:1.1em;
font-weight:bold;
}
.entity_profile .entity_fn dd:before { .entity_profile .entity_fn dd:before {
content: "("; content: "(";
font-weight:normal; font-weight:normal;
@ -574,10 +601,13 @@ display:block;
.form_user_block input.submit, .form_user_block input.submit,
.form_user_unblock input.submit, .form_user_unblock input.submit,
.form_group_block input.submit,
.form_group_unblock input.submit,
.entity_send-a-message a, .entity_send-a-message a,
.entity_edit a, .entity_edit a,
.form_user_nudge input.submit, .form_user_nudge input.submit,
.entity_nudge p { .entity_nudge p,
.form_make_admin input.submit {
border:0; border:0;
padding-left:20px; padding-left:20px;
} }
@ -640,6 +670,7 @@ list-style-type:none;
float:left; float:left;
margin-right:7px; margin-right:7px;
margin-bottom:7px; margin-bottom:7px;
display:inline;
} }
.section .entities li .photo { .section .entities li .photo {
margin-right:0; margin-right:0;
@ -712,12 +743,17 @@ float:left;
width:96.41%; width:96.41%;
border-width:1px; border-width:1px;
border-style:solid; border-style:solid;
padding:1.795%;
margin-bottom:11px; margin-bottom:11px;
} }
.notices li { .notices li {
list-style-type:none; list-style-type:none;
} }
.notices .notices {
margin-top:7px;
margin-left:5%;
width:95%;
float:left;
}
#aside_primary .notice, #aside_primary .notice,
#aside_primary .profile { #aside_primary .profile {
@ -773,6 +809,9 @@ float:left;
width:100%; width:100%;
overflow:hidden; overflow:hidden;
} }
.notice .entry-title.ov {
overflow:visible;
}
#shownotice .notice .entry-title { #shownotice .notice .entry-title {
font-size:2.2em; font-size:2.2em;
} }
@ -797,7 +836,7 @@ clear:left;
float:left; float:left;
font-size:0.95em; font-size:0.95em;
margin-left:59px; margin-left:59px;
width:65%; width:60%;
} }
#showstream .notice div.entry-content, #showstream .notice div.entry-content,
#shownotice .notice div.entry-content { #shownotice .notice div.entry-content {
@ -827,15 +866,12 @@ display:inline-block;
text-transform:lowercase; text-transform:lowercase;
} }
.notice-options { .notice-options {
padding-left:2%;
float:left;
width:50%;
position:relative; position:relative;
font-size:0.95em; font-size:0.95em;
width:12.5%; width:90px;
float:right; float:right;
margin-right:11px;
} }
.notice-options a { .notice-options a {
@ -896,6 +932,74 @@ border:0;
padding:0; padding:0;
} }
.notice .attachment {
position:relative;
padding-left:16px;
}
#attachments .attachment {
padding-left:0;
}
.notice .attachment img {
position:absolute;
top:18px;
left:0;
z-index:99;
}
#shownotice .notice .attachment img {
position:static;
}
#attachments {
clear:both;
float:left;
width:100%;
margin-top:18px;
}
#attachments dt {
font-weight:bold;
font-size:1.3em;
margin-bottom:4px;
}
#attachments ol li {
margin-bottom:18px;
list-style-type:decimal;
float:left;
clear:both;
}
#jOverlayContent,
#jOverlayContent #content,
#jOverlayContent #content_inner {
width: auto !important;
margin-bottom:0;
}
#jOverlayContent #content {
padding:11px;
min-height:auto;
}
#jOverlayContent .external span {
display:block;
margin-bottom:11px;
}
#jOverlayContent button {
position:absolute;
top:0;
right:0;
width:29px;
height:29px;
text-align:center;
font-weight:bold;
padding:0;
}
#jOverlayContent h1 {
max-width:475px;
}
#jOverlayContent #content {
border-radius:7px;
-moz-border-radius:7px;
-webkit-border-radius:7px;
}
#usergroups #new_group { #usergroups #new_group {
float: left; float: left;
@ -1019,8 +1123,6 @@ margin-left:18px;
} }
/* TOP_POSTERS */ /* TOP_POSTERS */
.section tbody td { .section tbody td {
padding-right:11px; padding-right:11px;
@ -1140,6 +1242,18 @@ width:400px;
margin-right:28px; margin-right:28px;
} }
#settings_design_color .form_data li {
width:33%;
}
#settings_design_color .form_data label {
float:none;
display:block;
}
#settings_design_color .form_data .swatch {
padding:11px;
margin-left:0;
}
.instructions ul { .instructions ul {
list-style-position:inside; list-style-position:inside;
} }

View File

@ -10,7 +10,7 @@
@import url(base.css); @import url(base.css);
html { html {
background:#fff url(../images/illustrations/illu_pigeons-01.png) no-repeat 0 100%; background:url(../images/illustrations/illu_pigeons-01.png) no-repeat 0 100%;
} }
body, body,
@ -30,10 +30,10 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
} }
input, textarea, select, input, textarea, select,
.entity_remote_subscribe { .entity_remote_subscribe {
border-color:#aaa; border-color:#AAAAAA;
} }
#filter_tags ul li { #filter_tags ul li {
border-color:#ddd; border-color:#DDDDDD;
} }
.form_settings input.form_action-primary { .form_settings input.form_action-primary {
@ -50,35 +50,41 @@ background-color:#8F0000;
input:focus, textarea:focus, select:focus, input:focus, textarea:focus, select:focus,
#form_notice.warning #notice_data-text { #form_notice.warning #notice_data-text {
border-color:#8F0000; border-color:#8F0000;
box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
-webkit-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
} }
input.submit, input.submit,
.entity_remote_subscribe { .entity_remote_subscribe {
color:#fff; color:#FFFFFF;
} }
a, a,
div.notice-options input, div.notice-options input,
.form_user_block input.submit, .form_user_block input.submit,
.form_user_unblock input.submit, .form_user_unblock input.submit,
.form_group_block input.submit,
.form_group_unblock input.submit,
.entity_send-a-message a, .entity_send-a-message a,
.form_user_nudge input.submit, .form_user_nudge input.submit,
.entity_nudge p, .entity_nudge p,
.form_settings input.form_action-primary { .form_settings input.form_action-primary,
color:#000; .form_make_admin input.submit {
color:#000000;
} }
.notice, .notice,
.profile { .profile {
border-color:#000; border-color:#000000;
} }
.notice a, .notice a,
.profile a { .profile a {
color:#fff; color:#FFFFFF;
} }
.notice:nth-child(3n-1), .notice:nth-child(3n-1),
.profile:nth-child(3n-1) { .profile:nth-child(3n-1) {
border-color:#fff; border-color:#FFFFFF;
} }
.notice:nth-child(3n-1) a, .notice:nth-child(3n-1) a,
.profile:nth-child(3n-1) a { .profile:nth-child(3n-1) a {
@ -90,7 +96,7 @@ border-color:#7F1114;
} }
.notice:nth-child(3n) a, .notice:nth-child(3n) a,
.profile:nth-child(3n) a { .profile:nth-child(3n) a {
color:#000; color:#000000;
} }
.aside .section .notice, .aside .section .notice,
@ -100,30 +106,30 @@ color:#000;
.aside .section .notice:nth-child(3n), .aside .section .notice:nth-child(3n),
.aside .section .profile:nth-child(3n) { .aside .section .profile:nth-child(3n) {
background-color:transparent; background-color:transparent;
color:#000; color:#000000;
} }
.aside .section { .aside .section {
border-color:#fff; border-color:#FFFFFF;
background-color:#fff; background-color:#FFFFFF;
color:#000; color:#000000;
} }
.aside .section:nth-child(n) { .aside .section:nth-child(n) {
border-color:#000; border-color:#000000;
background-color:#000; background-color:#000000;
color:#fff; color:#FFFFFF;
} }
.aside .section:nth-child(3n-1) { .aside .section:nth-child(3n-1) {
border-color:#fff; border-color:#FFFFFF;
background-color:#fff; background-color:#FFFFFF;
color:#000; color:#000000;
} }
.aside .section:nth-child(3n) { .aside .section:nth-child(3n) {
background-color:#7F1114; background-color:#7F1114;
border-color:#7F1114; border-color:#7F1114;
color:#000; color:#000000;
} }
.aside .section a { .aside .section a {
color:#7F1114; color:#7F1114;
@ -132,7 +138,7 @@ color:#7F1114;
color:#7F1114; color:#7F1114;
} }
.aside .section:nth-child(3n) a { .aside .section:nth-child(3n) a {
color:#fff; color:#FFFFFF;
} }
@ -145,33 +151,43 @@ background:url(../images/illustrations/illu_pigeons-02.png) no-repeat 10% 100%;
} }
#notice_text-count { #notice_text-count {
color:#333; color:#333333;
} }
#form_notice.warning #notice_text-count { #form_notice.warning #notice_text-count {
color:#000; color:#000000;
} }
#form_notice label[for=notice_data-attach] {
background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%;
}
#form_notice #notice_data-attach {
opacity:0;
}
#form_notice.processing #notice_action-submit { #form_notice.processing #notice_action-submit {
background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%; background:#FFFFFF url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
cursor:wait; cursor:wait;
text-indent:-9999px; text-indent:-9999px;
} }
#content, #content,
#site_nav_local_views a { #site_nav_local_views a {
border-color:#fff; border-color:#FFFFFF;
} }
#site_nav_local_views .current a { #site_nav_local_views .current a {
background-color:rgba(143, 0, 0, 0.8); background-color:rgba(143, 0, 0, 0.8);
color:#fff; color:#FFFFFF;
} }
#site_nav_local_views a { #site_nav_local_views a {
background-color:rgba(255, 255, 255, 0.3); background-color:rgba(255, 255, 255, 0.5);
} }
#site_nav_local_views a:hover { #site_nav_local_views a:hover {
background-color:#fff; background-color:rgba(255, 255, 255, 0.9);
color:#8F0000; color:#8F0000;
} }
#site_nav_local_views .current a {
text-shadow: rgba(194,194,194,0.5) 1px 1px 1px;
}
.error { .error {
background-color:#F7E8E8; background-color:#F7E8E8;
@ -181,7 +197,7 @@ background-color:#EFF3DC;
} }
#anon_notice { #anon_notice {
color:#000; color:#000000;
} }
@ -204,7 +220,10 @@ background-image:url(../../base/images/icons/icon_foaf.gif);
.form_user_nudge input.submit, .form_user_nudge input.submit,
.form_user_block input.submit, .form_user_block input.submit,
.form_user_unblock input.submit, .form_user_unblock input.submit,
.entity_nudge p { .form_group_block input.submit,
.form_group_unblock input.submit,
.entity_nudge p,
.form_make_admin input.submit {
background-position: 0 40%; background-position: 0 40%;
background-repeat: no-repeat; background-repeat: no-repeat;
background-color:transparent; background-color:transparent;
@ -214,7 +233,7 @@ background-color:transparent;
.form_user_subscribe input.submit, .form_user_subscribe input.submit,
.form_user_unsubscribe input.submit { .form_user_unsubscribe input.submit {
background-color:#8F0000; background-color:#8F0000;
color:#fff; color:#FFFFFF;
} }
.form_user_unsubscribe input.submit, .form_user_unsubscribe input.submit,
.form_group_leave input.submit, .form_group_leave input.submit,
@ -233,15 +252,22 @@ background-image:url(../../base/images/icons/twotone/green/quote.gif);
background-image:url(../../base/images/icons/twotone/green/mail.gif); background-image:url(../../base/images/icons/twotone/green/mail.gif);
} }
.form_user_block input.submit, .form_user_block input.submit,
.form_user_unblock input.submit { .form_user_unblock input.submit,
.form_group_block input.submit,
.form_group_unblock input.submit {
background-image:url(../../base/images/icons/twotone/green/shield.gif); background-image:url(../../base/images/icons/twotone/green/shield.gif);
} }
.form_make_admin input.submit {
background-image:url(../../base/images/icons/twotone/green/admin.gif);
}
/* NOTICES */ /* NOTICES */
.notices li.over { .notice .attachment {
background-color:#fcfcfc; background:transparent url(../../base/images/icons/twotone/green/clip-02.gif) no-repeat 0 45%;
}
#attachments .attachment {
background:none;
} }
.notice-options .notice_reply a, .notice-options .notice_reply a,
.notice-options form input.submit { .notice-options form input.submit {
background-color:transparent; background-color:transparent;
@ -263,17 +289,36 @@ background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-r
.notices div.notice-options { .notices div.notice-options {
opacity:0.4; opacity:0.4;
} }
.notices li.hover div.entry-content, .notices li:hover div.entry-content,
.notices li.hover div.notice-options { .notices li:hover div.notice-options {
opacity:1; opacity:1;
} }
div.entry-content { div.entry-content {
color:#333; color:#333333;
} }
div.notice-options a, div.notice-options a,
div.notice-options input { div.notice-options input {
font-family:sans-serif; font-family:sans-serif;
} }
#content .notices li:hover {
background-color:transparent;
}
#conversation .notices li:hover {
background-color:transparent;
}
.notices .notices {
background-color:rgba(200, 200, 200, 0.050);
}
.notices .notices .notices {
background-color:rgba(200, 200, 200, 0.100);
}
.notices .notices .notices .notices {
background-color:rgba(200, 200, 200, 0.150);
}
.notices .notices .notices .notices .notices {
background-color:rgba(200, 200, 200, 0.300);
}
/*END: NOTICES */ /*END: NOTICES */
#new_group a { #new_group a {
@ -283,7 +328,7 @@ background:transparent url(../../base/images/icons/twotone/green/news.gif) no-re
.pagination .nav_prev a, .pagination .nav_prev a,
.pagination .nav_next a { .pagination .nav_next a {
background-repeat:no-repeat; background-repeat:no-repeat;
border-color:#000; border-color:#000000;
} }
.pagination .nav_prev a { .pagination .nav_prev a {
background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);