Friday, August 24, 2018

iMessage App - Using a UITextField in compact presentation style

I'm simply trying to use a UITextField for my iMessage App.

The problem is with when it is in compact mode (MSMessagesAppPresentationStyleCompact) once you select the textfield, all the views disappear. It seems to work fine in expanded mode.

What is the proper way of using a textfield in compact mode? Thanks

Solved

It appears that you can only use textfields while in expanded mode, so you'll need to implement something like this:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    if([self presentationStyle] == MSMessagesAppPresentationStyleCompact) {
        [self requestPresentationStyle:MSMessagesAppPresentationStyleExpanded];
        self.didRequestKeyboard = YES;
        return NO;
    }

    return YES;
}

-(void)didTransitionToPresentationStyle:(MSMessagesAppPresentationStyle)presentationStyle {
    // Called after the extension transitions to a new presentation style.

    // Use this method to finalize any behaviors associated with the change in presentation style.
    if(presentationStyle == MSMessagesAppPresentationStyleExpanded){
        if(self.didRequestKeyboard){
            [self.textField becomeFirstResponder];
            self.didRequestKeyboard = NO;
        }
    }
}

I struggled with this problem (still present as of iOS 10.2) and ended on this workaround:

fileprivate class TextField: UITextField {
    override var canBecomeFirstResponder: Bool {
        if let viewController = viewController as? MSMessagesAppViewController,
           viewController.presentationStyle == .compact {
            viewController.requestPresentationStyle(.expanded)
            return false
        }
        return super.canBecomeFirstResponder
    }
}

I say "workaround" because I feel this is a problem Apple should solve ergo this solution should be temporary. This implementation, as an alternative to the original answer's, is segregated and can be easily ripped out.


Same solution but using blocks

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    if presentationStyle != .expanded {
        didTransitionHandler = {
            textField.becomeFirstResponder()
            self.didTransitionHandler = nil
        }

        requestPresentationStyle(.expanded)

        return false
    }

    return true
}

Monday, August 20, 2018

Customize UIDocumentMenuViewController look

Is it possible to customize the look of a UIDocumentMenuViewController instance, specifically the font? Our app uses a custom font throughout and the UIDocumentMenuViewController looks a little out of place. My gut is no, since the menu view is a UIRemoteView...

Sunday, August 19, 2018

AngularMaterialDemo/node_modules/rxjs/Rx"' has no exported member 'Subscribable'

I am implementing a sample application in Angular with AngularMaterial and FlexLayout .

I have successfully installed and implementing Angular Material Components.I have also installed Flex using the below command

npm install @angular/flex-layout --save

But when I am running my application I am getting the following warning message in my Eclipse Terminal as shown below

enter image description here

And I am also getting the following error in my console.

enter image description here

Below shown is package.json file

package.json:

{
  "name": "angular-material-demo",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^5.0.0",
    "@angular/cdk": "^5.0.3",
    "@angular/common": "^5.0.0",
    "@angular/compiler": "^5.0.0",
    "@angular/core": "^5.0.0",
    "@angular/flex-layout": "^6.0.0-beta.16",
    "@angular/forms": "^5.0.0",
    "@angular/http": "^5.0.0",
    "@angular/material": "^5.0.3",
    "@angular/platform-browser": "^5.0.0",
    "@angular/platform-browser-dynamic": "^5.0.0",
    "@angular/router": "^5.0.0",
    "@types/jwt-decode": "^2.2.1",
    "core-js": "^2.4.1",
    "font-awesome": "^4.6.3",
    "hammerjs": "^2.0.8",
    "jwt-decode": "^2.2.0",
    "primeng": "^2.0.5",
    "rxjs": "^5.5.2",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.6.0",
    "@angular/compiler-cli": "^5.0.0",
    "@angular/language-service": "^5.0.0",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "angular-ide": "^0.9.38",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.7.0",
    "typescript": "~2.4.2"
  }
}

I tried doing the below steps also.

Edited package.json: Had to change my version for @angular/compiler-cli. In my case I had to bring it back to 5.2.0, as it somehow got to 5.2.10.

Deleted the node_modules directory.

Ran: npm install

Installed: npm install @angular/flex-layout.

But again i ran in different errors. I also tried changing the version of flex from "@angular/flex-layout": "^6.0.0-beta.16" to "@angular/flex-layout": "^2.0.0-beta.12" in package.json file but I am still getting these errors.

Can anybody please help me to resolve this issue...?

Solved

Your problem is caused by having an old version of npm. To check you version use:

npm -v

Using apt install a very old version (3.5.2) of npm is installed. Upgrade to the latest by:

sudo npm install -g npm

Check your version again, you may have to open a terminal for it to refresh. As of July 4, 2018 the latest npm is 6.1.0. Clear the node_modules folder and redownload the modules:

rm -rf ./node_modules
npm install

try to upgrade your versions to

"typescript": "2.7.2" 
"@angular/cdk": "^5.2.4"
"@angular/material": "^5.2.4"

issue


Saturday, August 18, 2018

Update local properties from other clustered machines

We have a cluster consisting of 4 machines, one of them for backoffice. When I change a property from local.properties, I want to register it to the database and all machines should get the new value.

To do so, I create a CustomLocalProperty type for the new or altered property. When I change a property from backoffice machine, it is registered to the database and it is added to runtime properties via an interceptor(code piece is below) but other machines could not see the updated or new value.

How can I update this value from the other machines?

getConfiguration().addProperty(customLocalPropertyModel.getKey(), 
customLocalPropertyModel.getValue());

Solved

Here I can't see any benefit of using CustomLocalProperty, because the configuration always loads from your properties files. Instead what you can think of to broadcast your changes to other nodes and also update your local.properties source so next server build/restart get the updated value.

You can take help of Cluster-Aware Events to publish your changes to other nodes. Also refer to how cache invalidation handle in hybris cluster.


When customer thinks of changing a local property someday (For instance: product.price.minThreshold) , I do not want customer to enter Hac to do this action.

Customer can change this property or add a new local property from Backoffice in my case. I used CustomLocalPropertyModel to preserve customer changes on local properties and thus when Server restarts again, I can not lose customer changes and I can get them from database together with local.properties.

Firstly, I create an interceptor for CustomLocalPropertyModel called CustomLocalPropertyInterceptor and then fire(publish) an event called CustomLocalPropertyEvent in the interceptor. This event implements ClusterAwareEvent. I can reach other nodes with ClusterAwareEvent.(see below from official documentation)

Because the SAP Hybris Commerce can run in a cluster, it is possible to send an event from one node to a specific second node or broadcast events across all nodes of the cluster.You then have to implement the method publish(int sourceNodeId, int targetNodeId) in a way to return true if you want to publish the event the from the cluster node with the ID sourceNodeId to the node with the ID targetNodeId. Basically, return the boolean value of whether you wish to publish events from cluster node sourceNodeId to cluster node targetNodeId. Sometimes you want only a special node to receive event, for example the node that hosts an index service that needs to be informed of data changes. You should then return true if targetNodeId is equal to the ID of the node that hosts that index server.

@Override
public boolean publish(int sourceNodeId, int targetNodeId) {
    LOG.info("broadcast from all to all cluster nodes");
    return true;
}

You can keep your data in the event. Then i create class named CustomPropertyEventListener in order to capture the event on the other nodes and thus these nodes get new or altered value and add it to the their own hac via code piece below.

      configurationService.getConfiguration().addProperty(localPropertyKey,localPropertyValue);