### Install Rust using rustup Source: https://github.com/monal-im/monal/wiki/Building-Monal Installs the Rust programming language toolchain using rustup, the official Rust toolchain installer. This command downloads and runs the installation script from the official Rust website. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Install Project Dependencies with CocoaPods Source: https://github.com/monal-im/monal/wiki/Building-Monal Installs the project's dependencies using CocoaPods after ensuring the repository information is up-to-date. This command should be run from within the 'Monal' directory after cloning the repository. ```bash cd Monal pod install --repo-update ``` -------------------------------- ### Clone Monal Repository Source: https://github.com/monal-im/monal/wiki/Building-Monal Clones the Monal project repository from GitHub and navigates into the project directory. This is the first step in setting up the local development environment. ```bash git clone https://github.com/monal-im/Monal.git cd Monal ``` -------------------------------- ### Install CocoaPods using Homebrew Source: https://github.com/monal-im/monal/wiki/Building-Monal Installs the CocoaPods dependency manager using Homebrew. It is recommended to use Homebrew for installation to avoid potential errors. ```bash brew install cocoapods ``` -------------------------------- ### Data Form Query Examples (String) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Provides several examples of data-form subqueries as used in the Monal IM codebase. These illustrate different ways to specify namespaces, element names, item indices, and extraction commands for querying data forms. ```string {http://jabber.org/protocol/disco#info}query/\\{http://jabber.org/protocol/muc#roominfo}result@muc#roomconfig_roomname\\ ``` ```string {http://jabber.org/protocol/commands}command/\\\[0]@expire\\|datetime ``` ```string {http://jabber.org/protocol/commands}command/\\@expire\\|datetime ``` -------------------------------- ### Open Monal Project in Xcode Source: https://github.com/monal-im/monal/wiki/Building-Monal Opens the Monal project workspace in Xcode. This command assumes you are in the root directory of the cloned Monal repository. ```bash open Monal.xcworkspace ``` -------------------------------- ### Nest MLXMLNode Elements Example (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Demonstrates how to create a nested `MLXMLNode` structure, representing a complex XML stanza. This example shows the creation of a parent 'credentials' node with a child 'service' node, including attributes for the service. ```objc MLXMLNode* exampleNode = [[MLXMLNode alloc] initWithElement:@"credentials" andNamespace:@"urn:xmpp:extdisco:2" withAttributes:@{} andChildren:@[ [[MLXMLNode alloc] initWithElement:@"service" withAttributes:@{ @"type": service[@"type"], @"host": service[@"host"], @"port": service[@"port"], } andChildren:@[] andData:nil] ] andData:nil] ``` -------------------------------- ### Initialize and Update Git Submodules Source: https://github.com/monal-im/monal/wiki/Building-Monal Updates and initializes all git submodules for the Monal project, which are typically used for managing localizations. This command ensures that all necessary external components are fetched. ```bash git submodule update --init --recursive ``` -------------------------------- ### GPL Notice for Program Output (Interactive Mode) Source: https://github.com/monal-im/monal/blob/develop/Monal/opensource.html This is a template for a short notice displayed when a program starts in interactive mode. It informs the user about the program's warranty status and its free software nature, directing them to commands for more details. ```text {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type \`show w'. This is free software, and you are welcome to redistribute it under certain conditions; type \`show c' for details. ``` -------------------------------- ### Build Rust Libraries for Monal Source: https://github.com/monal-im/monal/wiki/Building-Monal Executes a script to build the Rust libraries required by the Monal project. This step is crucial for integrating Rust components into the main application. It requires the Rust toolchain to be set up. ```bash bash rust/build-rust.sh ``` -------------------------------- ### Swift Array and Dictionary Literals Source: https://github.com/monal-im/monal/wiki/Coding-style Provides an example of creating array and dictionary literals in Swift, demonstrating multi-line initialization for readability. ```swift return [ MyNewObject( bla: "yes", someMore: true, hasToBeDefinedHere: callThisMethodFor(moreInformation:"cool data", withSolution:42) ), MyNewObject( bla: "no", someMore: false, hasToBeDefinedHere: callThisMethodFor(moreInformation:"uncool data", withSolution:-1) ), ] ``` -------------------------------- ### Stream Log to UDP Server - Python Example Source: https://github.com/monal-im/monal/wiki/Introduction-to-Monal-Logging This Python script demonstrates how to set up a basic UDP log server to receive and process log data streamed from Monal. It requires Python 3 and can be configured with encryption keys, ports, and output file paths. The script supports command-line arguments for customization. ```python import argparse import socket def run_server(port, key, rawlog_file): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('0.0.0.0', port)) print(f"Listening on port {port}...") with open(rawlog_file, 'wb') as f: while True: data, addr = sock.recvfrom(10240) # TODO: Implement decryption using the provided key f.write(data) print(f"Received {len(data)} bytes from {addr}") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Monal UDP Log Server') parser.add_argument('-k', '--key', required=True, help='Encryption key') parser.add_argument('-p', '--port', type=int, required=True, help='Port to listen on') parser.add_argument('-r', '--rawlog', required=True, help='Path to save the rawlog file') args = parser.parse_args() run_server(args.port, args.key, args.rawlog) ``` -------------------------------- ### Make Rust Build Script Executable Source: https://github.com/monal-im/monal/wiki/Building-Monal Changes the permissions of the `build-rust.sh` script to make it executable. This is a prerequisite before running the script to build Rust libraries for the Monal project. ```bash chmod +x rust/build-rust.sh ``` -------------------------------- ### Fetch OMEMO Bundles (Objective-C) Source: https://github.com/monal-im/monal/wiki/Handler-Framework This example demonstrates fetching OMEMO encryption bundles for a given device ID. It uses the `fetchNode` method with a specific node format and a handler `handleBundleFetchResult` to process the outcome. The handler includes logic to manage successful fetches and log errors. ```Objective-C NSString* bundleNode = [NSString stringWithFormat:@"eu.siacs.conversations.axolotl.bundles:%@", deviceid]; [self.account.pubsub fetchNode:bundleNode from:jid withItemsList:nil andHandler:$newHandler(self, handleBundleFetchResult, $ID(rid, deviceid))]; ``` ```Objective-C $$instance_handler(handleBundleFetchResult, account.omemo, $$ID(xmpp*, account), $$ID(NSString*, jid), $$BOOL(success), $_ID(XMPPIQ*, errorIq), $_ID(NSString*, errorReason), $_ID((NSDictionary*), data), $$ID(NSString*, rid)) if(!success) { if(errorIq) DDLogError(@"Could not fetch bundle from %@: rid: %@ - %@", jid, rid, errorIq); else DDLogError(@"Could not fetch bundle from %@: rid: %@ - %@", jid, rid, errorReason); } else { // check that a corresponding buddy exists -> prevent foreign key errors MLXMLNode* receivedKeys = [data objectForKey:@"current"]; if(!receivedKeys && data.count == 1) { // some clients do not use receivedKeys = [[data allValues] firstObject]; } else if(!receivedKeys && data.count > 1) { DDLogWarn(@"More than one bundle item found from %@ rid: %@", jid, rid); } if(receivedKeys) { [self processOMEMOKeys:receivedKeys forJid:jid andRid:rid]; } } $$ ``` -------------------------------- ### Objective-C String Localization Source: https://github.com/monal-im/monal/wiki/Coding-style Provides an example of how to localize strings in Objective-C using NSLocalizedString. ```objc NSLocalizedString(@"Some text that should be translated", @"a note for our translators"); ``` -------------------------------- ### XML Path Query with Extraction and Conversion (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language An example of an XML path query that includes both element selection and an extraction/conversion command. This query targets a specific element and then extracts its text content, attempting to convert it to Base64 encoded data. ```objc // Example from codebase: {urn:xmpp:avatar:data}data#|base64 ``` -------------------------------- ### DNS SRV Records for XMPP Source: https://github.com/monal-im/monal/wiki/Considerations-for-XMPP-server-admins These DNS SRV records are crucial for directing XMPP client connections to the correct server and port, prioritizing TLS over StartTLS for improved connection efficiency and reliability, especially on mobile networks. ```dns _xmpps-client._tcp.example.net. 86400 IN SRV 5 0 5223 xmpp.example.net. _xmpp-client._tcp.example.net. 86400 IN SRV 50 0 5222 xmpp.example.net. ``` -------------------------------- ### XML Path Query for Specific Element (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language An example of an XML path query targeting a specific nested element with a given namespace and element name. This is used to locate particular pieces of information within larger XML stanzas, such as error details. ```objc // Example from codebase: error/{urn:ietf:params:xml:ns:xmpp-stanzas}item-not-found ``` -------------------------------- ### Select XML Nodes by Attribute Value (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Selects XML nodes based on attribute-value pairs. It supports verbatim matching and format string specifiers for dynamic values. The example demonstrates extracting a 'subscription' attribute's value by matching 'type' and 'jid' attributes. ```objc MLXMLNode* iq = ; NSString* subscriptionStatus = [iq findFirst:@"//{http://jabber.org/protocol/pubsub}pubsub/subscription@subscription", @"eu.siacs.conversations.axolotl.devicelist", @"user@example.com"]; MLAssert([subscriptionStatus isEqualToString:@"subscribed"], @"The extracted value of the subscription attribute should be 'subscribed'!"); ``` -------------------------------- ### Complex XML Path Query (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Provides an example of a complex XML path query used for selecting specific elements based on namespace, element name, and attribute conditions. This query syntax allows for precise targeting of nodes within an XML structure, often used for filtering or extracting specific data points. ```objc // Example from codebase: {urn:xmpp:jingle:1}jingle ``` -------------------------------- ### Extract Message ID from Root Element (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Shows how to extract the 'id' attribute from the root element using a rooted query. It uses the 'findFirst:' method to get a single string value. This method is useful for direct attribute retrieval. ```objc MLXMLNode* message = ; NSString* messageId = [message findFirst:@"/@id"]; MLAssert([messageId isEqualToString:@"some_id", @"The extracted message id should be 'some_id'!"); ``` -------------------------------- ### Query Data Form Field Value (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Extracts the integer value of a specific field from an XEP-0004 data form within an MLXMLNode. This example demonstrates querying the 'max-file-size' field from a form with a specific FORM_TYPE. It uses the '@fieldName|conversion' syntax. ```objc MLXMLNode* iqNode = ; NSInteger uploadSize = [[iqNode findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{urn:xmpp:http:upload:0}result@max-file-size\\|int"] integerValue]; MLAssert(uploadSize == 5242880, @"Extracted upload size should be 5242880 bytes!"); ``` -------------------------------- ### Create MLXMLNode Instances (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Provides several initializers for creating `MLXMLNode` objects, representing XML elements. These initializers allow specifying the element name, namespace, attributes, child nodes, and text data. Namespaces can be inherited from parent nodes if not explicitly provided. ```objc -(id) initWithElement:(NSString*) element; -(id) initWithElement:(NSString*) element andNamespace:(NSString*) xmlns; -(id) initWithElement:(NSString*) element andNamespace:(NSString*) xmlns withAttributes:(NSDictionary*) attributes andChildren:(NSArray*) children andData:(NSString* _Nullable) data; -(id) initWithElement:(NSString*) element withAttributes:(NSDictionary*) attributes andChildren:(NSArray*) children andData:(NSString* _Nullable) data; -(id) initWithElement:(NSString*) element andData:(NSString* _Nullable) data; -(id) initWithElement:(NSString*) element andNamespace:(NSString*) xmlns andData:(NSString* _Nullable) data; ``` -------------------------------- ### GPL Notice for Source Files (Text) Source: https://github.com/monal-im/monal/blob/develop/Monal/opensource.html This is a text-based notice to be included at the beginning of each source file to state the program's name, author, and licensing terms under the GPL. It ensures that the software is free and can be redistributed and modified. ```text {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} 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 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ``` -------------------------------- ### Call a Defined Handler in Objective-C Source: https://github.com/monal-im/monal/wiki/Handler-Framework Demonstrates how to create an MLHandler object using `$newHandler()` and then invoke it using the `$call()` method. This is the standard procedure for executing a defined handler. ```objectivec MLHandler* h = $newHandler(ClassName, myHandlerName); $call(h); ``` -------------------------------- ### Swift Conditional Statements (if/else/guard) Source: https://github.com/monal-im/monal/wiki/Coding-style Demonstrates Swift's if-else if-else syntax, highlighting the omission of parentheses around conditions. Also shows the use of guard statements for early exit conditions. ```swift if true == true or false == false { } else if ( some == other or true == false or isThisTrue() ) { } else { } // don't use an else branch if not needed because the if branch already returns // but: use guard statements if checking for some abort condition // to make clear that these are abort conditions if someThing { return } return ``` ```swift guard let result = somethingThatCouldBeNil() else { return } print(result) ``` -------------------------------- ### Query MLXMLNode with Custom Language (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Exposes three methods for querying `MLXMLNode` instances using a custom XML query language inspired by XPath. `find:` returns all matches, `findFirst:` returns the first match or nil, and `check:` returns a boolean indicating if any matches exist. These methods support printf-style format specifiers. ```objc -(NSArray*) find:(NSString* _Nonnull) queryString, ... NS_FORMAT_FUNCTION(1, 2); -(id) findFirst:(NSString* _Nonnull) queryString, ... NS_FORMAT_FUNCTION(1, 2); -(BOOL) check:(NSString* _Nonnull) queryString, ... NS_FORMAT_FUNCTION(1, 2); ``` -------------------------------- ### Objective-C Conditional Statements (if/else/switch) Source: https://github.com/monal-im/monal/wiki/Coding-style Demonstrates the standard syntax for if-else if-else blocks and switch statements in Objective-C. Includes best practices for default cases in switch statements. ```objc if() { } else if() { } else { } ``` ```objc switch() { case 0: break; case 1: break; default: unreachable(); // if the default case should never occur - MLConstants.h } ``` -------------------------------- ### Find Body Text with Inherited Namespace (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Demonstrates how to find all 'body' elements using an inherited namespace. It expects a single result and asserts its content. This relies on the 'find:' method of MLXMLNode. ```objc MLXMLNode* message = ; NSArray* bodyStrings = [message find:@"body#"]; MLAssert(bodyStrings.count == 1, @"Only one body text should be returned!"); MLAssert([bodyStrings[0] isEqualToString:@"Message text", @"The body with inherited namespace 'jabber:client' should be used!"); ``` -------------------------------- ### Swift Struct/Class Property and Method Ordering Source: https://github.com/monal-im/monal/wiki/Coding-style Details the preferred order of properties and methods within Swift structs or classes, including environment variables, state variables, initializers, computed properties, functions, and views. ```swift struct SomeView: View { // First of all, list all @Environment vars @Environment(\.presentationMode) private var presentationMode // Then list all @State, @StateObject etc. vars @State var mySolution = 42 // Then list all normal vars or let constants var xmppAccount: xmpp let seconds = 42 // Firs methods should always be init and deinit (if existing) init(contact: ObservableKVOWrapper) { [...] } deinit { [...] } // computed properties should come next var accountID: NSNumber { } // then all normal functions func doSomething(with solution: Int = 42) { // do it now! } // then all views (@ViewBuilder or not) @ViewBuilder var avatarView: some View { Text("World, Hello!") } // and last but not least the body of our view (if we are writing a View at all, of course) var body: some View { Text("Hello World!") } } ``` -------------------------------- ### Swift Variable and Constant Declarations Source: https://github.com/monal-im/monal/wiki/Coding-style Illustrates Swift's conventions for declaring mutable variables (var) and immutable constants (let) using camelCase. ```swift var varName: TypeName let varName: TypeName var varName = [...] let varName = [...] ``` -------------------------------- ### Enable XMPP Carbons (Objective-C) Source: https://github.com/monal-im/monal/wiki/Handler-Framework This snippet shows how to enable XMPP carbon features to archive messages. It checks for the presence of the carbons capability and sends an IQ stanza to the server. The handler `handleCarbonsEnabled` processes the server's response. ```Objective-C if([features containsObject:@"urn:xmpp:carbons:2"]) { DDLogInfo(@"got disco result with carbons ns"); if(!account.connectionProperties.usingCarbons2) { DDLogInfo(@"enabling carbons"); XMPPIQ* carbons = [[XMPPIQ alloc] initWithType:kiqSetType]; [carbons addChildNode:[[MLXMLNode alloc] initWithElement:@"enable" andNamespace:@"urn:xmpp:carbons:2"]]; [account sendIq:carbons withHandler:$newHandler(self, handleCarbonsEnabled)]; } } ``` ```Objective-C $$class_handler(handleCarbonsEnabled, $$ID(xmpp*, account), $$ID(XMPPIQ*, iqNode)) if([iqNode check:@"/"]) { DDLogWarn(@"carbon enable iq returned error: %@", [iqNode findFirst:@"error"]); [HelperTools postError:[NSString stringWithFormat:NSLocalizedString(@"Failed to enable carbons for account %@", @""), account.connectionProperties.identity.jid] withNode:iqNode andAccount:account andIsSevere:YES]; return; } account.connectionProperties.usingCarbons2 = YES; $$ ``` -------------------------------- ### Swift Switch Statement Source: https://github.com/monal-im/monal/wiki/Coding-style Shows the syntax for switch statements in Swift, including the use of default and unreachable for clarity. ```swift switch([...]) { case [...]: [...] case [...]: [...] default: unreachable("this should never happen"); // if the default case should never occur - SwiftHelpers.swift } ``` -------------------------------- ### Swift Function Declaration with Objective-C Export Source: https://github.com/monal-im/monal/wiki/Coding-style Shows how to declare Swift functions, emphasizing the use of proper argument labels and the @objc decorator for Objective-C compatibility and renaming. ```swift @objc(makeAccountPickerForContacts:andCallType:) func makeAccountPicker(for contacts: [MLContact], and callType: UInt) -> UIViewController { ``` -------------------------------- ### Objective-C Function Declaration and Swift Export Source: https://github.com/monal-im/monal/wiki/Coding-style Illustrates Objective-C function naming conventions, emphasizing descriptive names. Shows how to use NS_SWIFT_NAME for Swift export. ```objc -(NSNumber*) functionNameWithName1:(ParamType1) varName1 andName2:(ParamTypeWithPtr*) varName2 { } //this would be named isContactBlacklisted(forEncryption:) in Swift-land if we did not use NS_SWIFT_NAME to rename it +(BOOL) isContactBlacklistedForEncryption:(MLContact*) contact NS_SWIFT_NAME(isContactBlacklistedForEncryption(_:)); ``` -------------------------------- ### Extract All Attributes (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Illustrates extracting all attributes of a selected XML node. This returns a dictionary where keys are attribute names and values are their corresponding string representations. No conversion commands can be used with this extraction command. The '@@' extraction command is used. ```objc MLXMLNode* node = ; NSDictionary* attributes = [node findFirst:@"@@"]; ``` -------------------------------- ### Swift View Modifier Application Source: https://github.com/monal-im/monal/wiki/Coding-style Shows the recommended way to apply view modifiers in Swift, emphasizing indentation for readability and line breaks. ```swift // indent view modifiers below the view in question (and don't put them into the same line!) Text("Hello World!") .font(.largeTitle) .foregroundColor(.primary) // don't indent when coming after a closing "}" (but still use a new line!) Button { } .font(.largeTitle) .foregroundColor(.primary) ``` -------------------------------- ### XML Path Query for Nested Element (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Demonstrates an XML path query used to select a nested element within a specified namespace. This is common for accessing metadata or specific data structures within XMPP stanzas. ```objc // Example from codebase: {urn:xmpp:avatar:metadata}metadata/info ``` -------------------------------- ### Analyze Monal Battery Consumption with Python Source: https://github.com/monal-im/monal/wiki/Battery-consumption This Python script analyzes battery log files generated by the Apple Shortcut. It calculates and outputs the average and median battery discharge and charge over the recording period. This script is useful for developers and users who want to perform a detailed analysis of Monal's power consumption. ```python import argparse import json from statistics import mean, median def analyze_battery_logs(log_files): """Analyzes battery log files to calculate average and median discharge/charge. Args: log_files (list): A list of paths to the JSON log files. Returns: dict: A dictionary containing the analysis results. """ discharge_periods = [] charge_periods = [] for log_file in log_files: with open(log_file, 'r') as f: data = json.load(f) for entry in data: if 'powerState' in entry: power_state = entry['powerState'] timestamp = entry['timestamp'] if power_state == 'discharging': discharge_periods.append({'timestamp': timestamp}) elif power_state == 'charging': charge_periods.append({'timestamp': timestamp}) results = {} if discharge_periods: discharge_timestamps = [p['timestamp'] for p in discharge_periods] discharge_durations = [ discharge_timestamps[i+1] - discharge_timestamps[i] for i in range(len(discharge_timestamps) - 1) ] results['average_discharge_duration'] = mean(discharge_durations) results['median_discharge_duration'] = median(discharge_durations) else: results['average_discharge_duration'] = 0 results['median_discharge_duration'] = 0 if charge_periods: charge_timestamps = [p['timestamp'] for p in charge_periods] charge_durations = [ charge_timestamps[i+1] - charge_timestamps[i] for i in range(len(charge_timestamps) - 1) ] results['average_charge_duration'] = mean(charge_durations) results['median_charge_duration'] = median(charge_durations) else: results['average_charge_duration'] = 0 results['median_charge_duration'] = 0 return results if __name__ == "__main__": parser = argparse.ArgumentParser(description='Analyze Monal battery logs.') parser.add_argument('log_files', metavar='L', type=str, nargs='+', help='List of JSON battery log files to analyze.') args = parser.parse_args() analysis_results = analyze_battery_logs(args.log_files) print("--- Battery Consumption Analysis ---") print(f"Average Discharge Duration: {analysis_results['average_discharge_duration']:.2f} seconds") print(f"Median Discharge Duration: {analysis_results['median_discharge_duration']:.2f} seconds") print(f"Average Charge Duration: {analysis_results['average_charge_duration']:.2f} seconds") print(f"Median Charge Duration: {analysis_results['median_charge_duration']:.2f} seconds") ``` -------------------------------- ### Objective-C Variable and Define Declarations Source: https://github.com/monal-im/monal/wiki/Coding-style Shows the conventions for declaring variables using camelCase and defines using UPPER_CASE in Objective-C. ```objc Type* varName; ``` ```objc #define SHORT_PING 16.0 ``` -------------------------------- ### Extract Base64 Encoded Data (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Illustrates extracting an attribute value that is Base64 encoded and converting it into NSData. This is useful for handling binary data embedded within XML, such as avatar data. The `findFirst:` method is used with an extraction command and a '|base64' conversion command. ```objc MLXMLNode* node = ; NSData* decodedData = [node findFirst:@"@some_attribute|base64"]; ``` -------------------------------- ### Define Instance Handler in Objective-C Source: https://github.com/monal-im/monal/wiki/Handler-Framework Defines an instance method to be used as a Monal handler. It requires specifying an instance to operate on, extracted via a statement. 'self' within the handler refers to this extracted instance. ```objectivec $$instance_handler(myHandlerName, instanceToUse, $$ID(xmpp*, account), $$BOOL(success)) // your code comes here // 'self' is now the instance of the class extracted by the instanceToUse statement. // instead of the class instance as it would be if $$class_handler() was used instead of $$instance_handler() // variables defined/imported: account, success (both mandatory) $$ ``` -------------------------------- ### Extract and Convert Attribute to Boolean (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Demonstrates extracting an attribute's value and converting it to a boolean. This is useful for checking flag-like attributes in XML stanzas, such as the 'complete' attribute in XEP-0004 Message Archive Management (MAM). The `findFirst:` method is used with an extraction command '@attributeName' and a conversion command '|bool'. ```objc MLXMLNode* iqNode = ; if([[iqNode findFirst:@"{urn:xmpp:mam:2}fin@complete|bool"] boolValue]) DDLogInfo(@"Mam query finished") ``` -------------------------------- ### Extract Element Name (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Demonstrates extracting the name of an XML element. This command is particularly useful when dealing with wildcard element names or negated element names in path queries. The '$' extraction command is used to retrieve the element name as an NSString. ```objc MLXMLNode* node = ; NSString* elementName = [node findFirst:@"$"]; ``` -------------------------------- ### Extract and Convert Attribute to Datetime (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Shows how to extract a timestamp attribute and convert it into an NSDate object. This is commonly used for parsing date/time information from XML elements, such as the 'stamp' attribute in XMPP delay messages. The `findFirst:` method is employed with an extraction command '@attributeName' and a conversion command '|datetime'. ```objc MLXMLNode* messageNode = ; NSDate* delayStamp = [messageNode findFirst:@"{urn:xmpp:delay}delay@stamp|datetime"]; MLAssert(delayStamp.timeIntervalSince1970 == 1031699305, @"The delay stamp should be 1031699305 seconds after the epoch!"); ``` -------------------------------- ### Swift: Translate Text Views and NSLocalizedString Source: https://github.com/monal-im/monal/wiki/Coding-style Demonstrates how to make strings translatable in Swift using `Text()` views and `NSLocalizedString`. Non-translatable strings within `Text()` views or functions using `LocalizedStringKey` are also highlighted. Ensures correct localization practices by using `NSLocalizedString` for non-UI text elements. ```swift Text("This will be translatable) someCoolFunction("This will NOT be translatable, even if this function uses LocalizedStringKey!") someCoolFunction(NSLocalizedString("This is translatable again", comment:"a note for our translators") ``` -------------------------------- ### Bind Variables When Creating Handler in Objective-C Source: https://github.com/monal-im/monal/wiki/Handler-Framework Shows how to bind variables during the creation of an MLHandler object using `$newHandler()` and also during invocation with `$call()`. Variables bound at creation must conform to NSCoding for serialization. Invocation-time variables can overwrite creation-time ones with the same name. ```objectivec NSString* var1 = @"value"; MLHandler* h = $newHandler(ClassName, myHandlerName, $ID(var1), $BOOL(success, YES) )); xmpp* account = nil; $call(h, $ID(account), $ID(otherAccountVarWithSameValue, account)) ``` -------------------------------- ### Extract Text Content (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Shows how to extract the text content of an XML node. This is useful for retrieving string values directly within an element. The '#' extraction command is used, and the result can be further processed with conversion commands. It returns an NSString. ```objc MLXMLNode* node = ; NSString* textContent = [node findFirst:@"#"]; ``` -------------------------------- ### Exclude XML Nodes by Name (Objective-C) Source: https://github.com/monal-im/monal/wiki/XML-Query-Language Selects all XML nodes that do not have a specified name. This is achieved by prefixing the element name with '!'. It requires an MLXMLNode object and returns the first matching node's name. ```objc MLXMLNode* streamError = ; NSString* errorReason = [streamError findFirst:@"{urn:ietf:params:xml:ns:xmpp-streams}!text$"]; MLAssert([errorReason isEqualToString:@"not-well-formed"], @"The extracted error should be 'not-well-formed'!"); ``` -------------------------------- ### Define Class Handler in Objective-C Source: https://github.com/monal-im/monal/wiki/Handler-Framework Defines a static class method to be used as a Monal handler. Arguments prefixed with $$ are mandatory, while $_ are optional. Primitive data types are always mandatory. This method is usable without explicit interface declaration. ```objectivec $$class_handler(myHandlerName, $_ID(xmpp*, account), $$BOOL(success)) // your code comes here // variables defined/imported: account (optional), success (mandatory) $$ ``` -------------------------------- ### Create Handler with Invalidation in Objective-C Source: https://github.com/monal-im/monal/wiki/Handler-Framework Illustrates creating an MLHandler object with an associated invalidation handler using `$newHandlerWithInvalidation()`. Once invalidated, a handler cannot be called or invalidated again. Both normal and invalidation handlers can be class or instance handlers. ```objectivec // definition of normal handler method as instance_handler $$instance_handler(myHandlerName, [account getInstanceToUse], $_ID(xmpp*, account), $$BOOL(success)) // your code comes here // 'self' is now the instance of the class extracted by [account getInstanceToUse] // instead of the class instance as it would be if $$class_handler() was used instead of $$instance_handler() $$ // definition of invalidation method $$class_handler(myInvalidationHandlerName, $$BOOL(done), $_ID(NSString*, var1)) // your code comes here // variables imported: var1, done // variables that could have been imported according to $newHandler and $call below: var1, success, done $$ MLHandler* h = $newHandlerWithInvalidation(ClassName, myHandlerName, myInvalidationHandlerName, $ID(var1, @"value"), $BOOL(success, YES) )); // call invalidation method with "done" argument set to YES $invalidate(h, $BOOL(done, YES)) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.