Permalink
Browse files

Made page member list editable

...as long as you're the page owner.

Adding a member to a page also adds her to the member list of the
page's wiki, if necessary.
  • Loading branch information...
1 parent 200bbc0 commit 1224ce013c71fdb955f19d9f5ddff571d25201c6 @snej snej committed Jan 21, 2013
Showing with 131 additions and 46 deletions.
  1. +62 −32 TouchWiki/PageController.m
  2. +46 −4 TouchWiki/PageTemplate.html
  3. +2 −0 TouchWiki/WikiItem.h
  4. +21 −0 TouchWiki/WikiItem.m
  5. +0 −10 TouchWiki/WikiPage.m
@@ -24,7 +24,7 @@
#define kFlipToPreviewAnimation UIViewAnimationOptionTransitionFlipFromRight
-static NSString *sHTMLPrefix, *sHTMLSuffix;
+static NSString *sHTMLTemplate;
static NSRegularExpression* sExplicitWikiWordRegex;
static NSRegularExpression* sImplicitWikiWordRegex;
@@ -54,13 +54,10 @@ @implementation PageController
+ (void) initialize {
- if (!sHTMLPrefix) {
+ if (!sHTMLTemplate) {
NSURL* url = [[NSBundle bundleForClass: self] URLForResource: @"PageTemplate" withExtension: @"html"];
- NSString* html = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error: nil];
- NSArray* parts = [html componentsSeparatedByString: @"{{BODY}}"];
- NSAssert(parts.count == 2, @"PageTemplate.html does not contain {{BODY}}");
- sHTMLPrefix = parts[0];
- sHTMLSuffix = parts[1];
+ sHTMLTemplate = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error: nil];
+ NSAssert(sHTMLTemplate != nil, @"Can't load PageTemplate.html");
sExplicitWikiWordRegex =
[NSRegularExpression regularExpressionWithPattern: @"\\[\\[([\\w ]+)\\]\\]"
@@ -152,23 +149,36 @@ - (void) configureButtons {
}
+static void replace(NSMutableString* str, NSString* pattern, NSString* replacement) {
+ if (!replacement)
+ replacement = @"";
+ [str replaceOccurrencesOfString: pattern withString: replacement
+ options: 0 range: NSMakeRange(0, str.length)];
+}
+
+
- (void) loadContent {
- if (_page)
- self.title = [NSString stringWithFormat: @"%@ » %@", _page.wiki.title, _page.title];
- else
+ if (!_page) {
self.title = NSLocalizedString(@"No Page", @"No Page");
+ [_webView loadHTMLString: @"" baseURL: nil];
+ return;
+ }
+
+ self.title = [NSString stringWithFormat: @"%@ » %@", _page.wiki.title, _page.title];
+ NSMutableString* html = [sHTMLTemplate mutableCopy];
- NSMutableString* html = [sHTMLPrefix mutableCopy];
+ NSString* klass = _page.owned ? @"owned" : (_page.editable ? @"unlocked" : @"locked");
+
+ //FIX: Use a real template engine!
+ replace(html, @"{{ACCESSCLASS}}", klass);
+ replace(html, @"{{OWNER}}", _page.owner_id);
+ replace(html, @"{{MEMBERS}}", [_page.members componentsJoinedByString: @", "]);
- if (_page && !_page.owned) {
- NSString* klass = _page.editable ? @"unlocked" : @"locked";
- [html appendFormat: @"<div id='access' class='%@'>Owner: %@</div>\n",
- klass, _page.owner_id];
- }
if (_page.draft) {
[html appendString: @"<div id='banner'>PREVIEW</div>\n"];
}
+ NSMutableString* bodyHTML = [NSMutableString string];
NSMutableString* markdown = _page.markdown.mutableCopy;
if (markdown.length > 0) {
// Markdown parsing:
@@ -179,7 +189,7 @@ - (void) loadContent {
// Implicit wiki-word matching -- matches all words in CamelCase.
// Generates a different (unobtrusive) style of link if the word does not match a page.
NSString* origHTML = [GHMarkdownParser flavoredHTMLStringFromMarkdownString: markdown];
- NSMutableString* replacedHTML = [origHTML mutableCopy];
+ bodyHTML = [origHTML mutableCopy];
__block int offset = 0;
NSSet* titles = _page.wiki.allPageTitles;
NSString* curTitle = _page.title;
@@ -196,12 +206,11 @@ - (void) loadContent {
NSString* replacement = [NSString stringWithFormat: @"<a class='%@' href='wiki:%@'>%@</a>",
klass, word, word];
range.location += offset;
- [replacedHTML replaceCharactersInRange: range withString: replacement];
+ [bodyHTML replaceCharactersInRange: range withString: replacement];
offset += replacement.length - range.length;
}];
- [html appendString: replacedHTML];
}
- [html appendString: sHTMLSuffix];
+ replace(html, @"{{BODY}}", bodyHTML);
[_webView loadHTMLString: html baseURL: nil];
//NSLog(@"HTML = %@", html);
}
@@ -359,24 +368,45 @@ - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)butto
}
+- (void) updateMembers: (NSArray*)members {
+ members = [[NSOrderedSet orderedSetWithArray: members] array]; // Remove duplicates
+ _page.members = members;
+ [_page.wiki addMembers: members];
+}
+
+
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
- if (navigationType != UIWebViewNavigationTypeLinkClicked)
- return YES;
NSURL* url = request.URL;
- if ([url.scheme isEqualToString: @"wiki"]) {
- NSString* title = [url.resourceSpecifier stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
- NSLog(@"Link to '%@'", title);
- [self performSelector: @selector(goToPageNamed:) withObject: title afterDelay: 0.0];
- } else if ([[UIApplication sharedApplication] canOpenURL: url]) {
- [self performSelector: @selector(goToExternalURL:) withObject: url afterDelay: 0.0];
- } else {
- NSString* message = [NSString stringWithFormat: @"Couldn't open URL <%@>", url.absoluteString];
- [gAppDelegate showAlert: message error: nil fatal: NO];
+ if (navigationType == UIWebViewNavigationTypeLinkClicked) {
+ if ([url.scheme isEqualToString: @"wiki"]) {
+ NSString* title = [url.resourceSpecifier stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
+ NSLog(@"Link to '%@'", title);
+ [self performSelector: @selector(goToPageNamed:) withObject: title afterDelay: 0.0];
+ } else if ([[UIApplication sharedApplication] canOpenURL: url]) {
+ [self performSelector: @selector(goToExternalURL:) withObject: url afterDelay: 0.0];
+ } else {
+ NSString* message = [NSString stringWithFormat: @"Couldn't open URL <%@>", url.absoluteString];
+ [gAppDelegate showAlert: message error: nil fatal: NO];
+ }
+ return NO;
+
+ } else if (navigationType == UIWebViewNavigationTypeOther) {
+ if ([url.scheme isEqualToString: @"wikicmd"]) {
+ NSArray* items = [url.path componentsSeparatedByString: @"/"];
+ NSString* cmd = items[1];
+ items = [items subarrayWithRange: NSMakeRange(2, items.count - 2)];
+ if ([cmd isEqualToString: @"setMembers"]) {
+ [self updateMembers: items];
+ } else {
+ NSLog(@"Warning: WebView sent unknown command '%@'", cmd);
+ }
+ return NO;
+ }
}
- return NO;
+ return YES;
}
@@ -27,17 +27,17 @@
color: rgba(255, 0, 0, 0.1);
-webkit-transform: rotate(15deg);
}
+
#access {
position: fixed;
top: 5px;
right: -1px;
- width: 100px;
+ width: 200px;
padding: 2px;
border: 1px solid lightgray;
background-color: yellow;
font-family: "Avenir Next", sans-serif;
- font-size: 75%;
- text-align: center;
+ font-size: 60%;
}
#access.locked:before {
content: "🔒 ";
@@ -46,11 +46,24 @@
background-color: gray;
color: white;
}
- #access.unlocked:before {
+ #access.unlocked:before,
+ #access.owned.before {
content: "🔓 ";
}
#access.unlocked {
}
+ .editButton {
+ display: none;
+ }
+ #access.owned .editbutton {
+ display: inline;
+ }
+
+ #membersEdit {
+ display: none;
+ width: 180px;
+ }
+
p { /* http://stackoverflow.com/questions/5356752/webkit-hyphenation */
hyphens:auto;
text-align:justify;
@@ -69,9 +82,38 @@
padding-bottom: -5px;
}
</style>
+
+ <script>
+ function editMembers(button) {
+ var span = document.getElementById("members");
+ var area = document.getElementById("membersEdit");
+ if (area.style.display != "block") {
+ span.style.display = "none";
+ area.style.display = "block";
+ area.value = span.innerText;
+ area.focus();
+ button.innerText = "Done";
+ } else {
+ var members = area.value.split(/\s*(?:,|\s)\s*/); // comma or space
+ span.style.display = "inline";
+ area.style.display = "none";
+ span.innerText = members.join(", ");
+ button.innerText = "Edit";
+ window.location = "wikicmd:///setMembers/" + members.join("/");
+ }
+ }
+ </script>
</head>
+
<body>
<div id="container">
+ <div id='access' class='{{ACCESSCLASS}}'>
+ <strong>Owner:</strong> {{OWNER}}<br />
+ <strong>Members:</strong> <span id="members">{{MEMBERS}}</span>
+ <textarea id="membersEdit" autocorrect='off' autocapitalize='none'></textarea>
+ <button class="editbutton" onclick="editMembers(this)">Edit</button>
+ </div>
+
{{BODY}}
</div>
</body>
@@ -23,6 +23,8 @@
@property (readonly) NSString* owner_id;
@property (copy) NSArray* members;
+- (void) addMembers: (NSArray*)newMembers;
+
@property (readonly) bool editable;
@property (readonly) bool owned;
View
@@ -21,6 +21,15 @@ @implementation WikiItem
@dynamic title, markdown, created_at, updated_at, owner_id, members;
+- (id) initWithDocument: (TDDocument*)document {
+ self = [super initWithDocument: document];
+ if (self) {
+ self.autosaves = true;
+ }
+ return self;
+}
+
+
- (void) setType: (NSString*)type owner: (NSString*)owner {
NSParameterAssert(owner.length > 0);
[self setValue: type ofProperty: @"type"];
@@ -58,4 +67,16 @@ - (bool) owned {
}
+- (void) addMembers: (NSArray*)newMembers {
+ NSArray* oldMembers = self.members;
+ if (!oldMembers) {
+ self.members = newMembers;
+ return;
+ }
+ NSMutableOrderedSet* members = [NSMutableOrderedSet orderedSetWithArray: self.members];
+ [members addObjectsFromArray: newMembers];
+ self.members = members.array;
+}
+
+
@end
View
@@ -32,16 +32,6 @@ - (id) initNewWithTitle: (NSString*)title inWiki: (Wiki*)wiki {
return self;
}
-
-- (id) initWithDocument: (TDDocument*)document {
- self = [super initWithDocument: document];
- if (self) {
- self.autosaves = true;
- }
- return self;
-}
-
-
- (NSString*) title {
NSString *wikiID, *title;
if (![[self class] parseDocID: self.document.documentID intoWikiID: &wikiID andTitle: &title])

0 comments on commit 1224ce0

Please sign in to comment.