", "").replace("
", "").replace("", "").replace("", ""))); + + + holder.contentArea.setData(data); + + if (position == getCount() - 1) { + loadMore.loadMore(); + } + + return convertView; + } + + class ViewHolder { + + public ViewHolder(View v) { + icon = (ImageView) v.findViewById(R.id.icon); + name = (TextView) v.findViewById(R.id.name); + time = (TextView) v.findViewById(R.id.time); + content = (TextView) v.findViewById(R.id.content); + contentArea = new ContentArea(v, clickListItem, onClickImage, myImageGetter, imageLoadTool, mPxImageWidth); + } + + ImageView icon; + TextView name; + TextView time; + TextView content; + + ContentArea contentArea; + } + +} diff --git a/app/src/enterprise/java/net/coding/program/project/maopao/EnterpriseProjectMaopaoEditFragment.java b/app/src/enterprise/java/net/coding/program/project/maopao/EnterpriseProjectMaopaoEditFragment.java new file mode 100644 index 000000000..809e971c9 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/project/maopao/EnterpriseProjectMaopaoEditFragment.java @@ -0,0 +1,93 @@ +package net.coding.program.project.maopao; + + +import android.net.Uri; +import android.support.annotation.NonNull; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.model.ProjectObject; +import net.coding.program.common.util.FileUtil; +import net.coding.program.common.widget.UploadHelp; +import net.coding.program.network.HttpObserver; +import net.coding.program.network.Network; +import net.coding.program.network.model.file.CodingFile; +import net.coding.program.task.TaskDespEditFragment; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EFragment; + +import java.io.File; + +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +@EFragment(R.layout.fragment_topic_edit) +public class EnterpriseProjectMaopaoEditFragment extends TaskDespEditFragment { + + @AfterViews + void initProjectMaopaoEditFragment() { + edit.setHint(R.string.input_project_maopao_content); + } + + @Override + protected String getCustomUploadPhoto() { + return Global.HOST_API + "/tweet/insert_image"; + } + + @Override + protected void updateImage(Uri updateFileUri) { + String path = getProjectPath(); + if (path.startsWith("/")) { + String[] split = path.toLowerCase().replace("/user/", "").replace("/project", "").split("/"); + Network.getRetrofit(getContext()) + .getProject(split[0], split[1]) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new HttpObserver(getContext()) { + @Override + public void onSuccess(ProjectObject data) { + super.onSuccess(data); + + realUpdateImage(updateFileUri, data.id); + } + + @Override + public void onFail(int errorCode, @NonNull String error) { + super.onFail(errorCode, error); + showProgressBar(false); + } + }); + } else { + try { + int projectId = Integer.valueOf(path); + realUpdateImage(updateFileUri, projectId); + } catch (Exception e) { + showProgressBar(false); + showButtomToast("项目路径错误 " + path); + } + } + } + + private void realUpdateImage(Uri updateFileUri, int projectId) { + UploadHelp help = new UploadHelp(getContext(), projectId, 0, + new File(FileUtil.getPath(getContext(), updateFileUri)), + new UploadHelp.NetworkRequest() { + @Override + public void onProgress(int progress) { + } + + @Override + public void onSuccess(CodingFile codingFile) { + uploadImageSuccess(codingFile.ownerPreview); + showProgressBar(false); + } + + @Override + public void onFail() { + showProgressBar(false); + } + }, false); + help.upload(); + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/CommonPickProjectActivity.java b/app/src/enterprise/java/net/coding/program/setting/CommonPickProjectActivity.java new file mode 100644 index 000000000..ef16e9f13 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/CommonPickProjectActivity.java @@ -0,0 +1,190 @@ +package net.coding.program.setting; + +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerviewViewHolder; + +import net.coding.program.R; +import net.coding.program.common.GlobalData; +import net.coding.program.common.ImageLoadTool; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.common.ui.shadow.RecyclerViewSpace; +import net.coding.program.common.widget.CommonAdapter; +import net.coding.program.common.widget.CommonListView; +import net.coding.program.network.HttpObserver; +import net.coding.program.network.Network; +import net.coding.program.network.model.user.Member; +import net.coding.program.network.model.user.MemberRole; +import net.coding.program.project.detail.MemberAuthorityActivity_; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.OnActivityResult; +import org.androidannotations.annotations.ViewById; + +import java.util.ArrayList; +import java.util.List; + +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +// 从企业所有项目中选择一个项目进行操作 +@EActivity(R.layout.common_simple_listview) +public class CommonPickProjectActivity extends BackActivity { + + private static final int RESULT_SET_AUTHORITY = 1; + + @Extra + Member member; + + @ViewById + CommonListView listView; + + ProjectAdapter adapter; + + ArrayList listData = new ArrayList<>(); + + @AfterViews + void initCommonPickProjectActivity() { + listView.setLayoutManager(new LinearLayoutManager(this)); + listView.addItemDecoration(new RecyclerViewSpace(this)); + + adapter = new ProjectAdapter(listData); + listView.setAdapter(adapter); + listView.setDefaultOnRefreshListener(() -> onRefresh()); + listView.enableDefaultSwipeRefresh(true); + + onRefresh(); + } + + private void onRefresh() { + Network.getRetrofit(CommonPickProjectActivity.this, listView) + .getUserJoinedProjects(GlobalData.getEnterpriseGK(), member.user.global_key) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new HttpObserver >(this, listView) { + @Override + public void onSuccess(List
data) { + super.onSuccess(data); + listData.clear(); + listData.addAll(data); + adapter.notifyDataSetChanged(); + } + }); + } + + protected class ProjectAdapter extends CommonAdapter { + + public ProjectAdapter(List list) { + super(list); + } + + @Override + protected int getNormalLayoutResId() { + return R.layout.common_pick_project_list_item; + } + + @Override + protected ProjectHolder newViewHolder(View view) { + ProjectHolder holder = new ProjectHolder(view); + holder.rootLayout.setOnClickListener(clickItem); + return holder; + } + + @Override + protected void withBindHolder(ProjectHolder holder, MemberRole data, int position) { + MemberRole item = getItem(position); + holder.name.setText(item.project.name); + holder.authority.setText(data.getAuthority().projectName); + holder.rootLayout.setTag(item); + iconfromNetwork(holder.image, item.project.icon, ImageLoadTool.optionsRounded2); + } + + @Override + public long generateHeaderId(int i) { + return super.generateHeaderId(i); + } + + @Override + public ProjectHolder newHeaderHolder(View view) { + return new ProjectHolder(view, true); + } + + @Override + public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder, int pos) { + super.onBindHeaderViewHolder(viewHolder, pos); + } + + @Override + public UltimateRecyclerviewViewHolder onCreateHeaderViewHolder(ViewGroup parent) { + return super.onCreateHeaderViewHolder(parent); + } + + @Override + public boolean hasHeaderView() { + return super.hasHeaderView(); + } + + @Override + public long getHeaderId(int position) { + return super.getHeaderId(position); + } + + @Override + public ProjectHolder newFooterHolder(View view) { + return new ProjectHolder(view, true); + } + } + + public static class ProjectHolder extends UltimateRecyclerviewViewHolder { + + public TextView name; + public ImageView image; + public TextView authority; + public View rootLayout; + + public ProjectHolder(View view, boolean isHeader) { + super(view); + } + + public ProjectHolder(View view) { + super(view); + rootLayout = view; + name = (TextView) view.findViewById(R.id.name); + authority = (TextView) view.findViewById(R.id.authority); + image = (ImageView) view.findViewById(R.id.icon); + } + } + + private View.OnClickListener clickItem = v -> { + Object object = v.getTag(); + if (object instanceof MemberRole) { + MemberRole item = (MemberRole) object; + MemberAuthorityActivity_.intent(CommonPickProjectActivity.this) + .globayKey(member.user.global_key) + .authority(item.getAuthority()) + .projectId(item.projectId) + .startForResult(RESULT_SET_AUTHORITY); + } + }; + + @OnActivityResult(RESULT_SET_AUTHORITY) + void onResultSetAuthority(int result, @OnActivityResult.Extra int intentData, + @OnActivityResult.Extra int intentData1) { + if (result == RESULT_OK) { + for (MemberRole item : listData) { + if (item.projectId == intentData1) { + item.type = intentData; + adapter.notifyDataSetChanged(); + break; + } + } + } + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/EnterpriseAccountActivity.java b/app/src/enterprise/java/net/coding/program/setting/EnterpriseAccountActivity.java new file mode 100644 index 000000000..f1f6eac8f --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/EnterpriseAccountActivity.java @@ -0,0 +1,173 @@ +package net.coding.program.setting; + +import android.app.Activity; +import android.os.Build; +import android.support.v7.widget.Toolbar; +import android.text.Spanned; +import android.view.View; +import android.widget.TextView; + +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; + +import de.hdodenhof.circleimageview.CircleImageView; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.GlobalData; +import net.coding.program.common.base.MyJsonResponse; +import net.coding.program.common.model.EnterpriseAccount; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.network.MyAsyncHttpClient; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.setting.order.OrderMainActivity_; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.OnActivityResult; +import org.androidannotations.annotations.OptionsItem; +import org.androidannotations.annotations.OptionsMenu; +import org.androidannotations.annotations.ViewById; +import org.androidannotations.annotations.res.ColorRes; +import org.json.JSONObject; + +@EActivity(R.layout.activity_enterprise_account) +@OptionsMenu(R.menu.enterprise_account_menu) +public class EnterpriseAccountActivity extends BackActivity { + + private static final int SETTING_REQUEST_CODE = 1000; + + // 默认企业头像,只在企业设置界面用到 + public static final DisplayImageOptions enterpriseIconOptions = new DisplayImageOptions + .Builder() + .showImageOnLoading(R.drawable.icon_user_monkey_circle) + .showImageForEmptyUri(R.drawable.icon_user_monkey_circle) + .showImageOnFail(R.drawable.icon_user_monkey_circle) + .cacheInMemory(true) + .cacheOnDisk(true) + .considerExifParams(true) + .build(); + + @ViewById + TextView accountState; + @ViewById + CircleImageView companyIcon; + @ViewById + TextView companyName; + @ViewById + Toolbar toolbar; + + EnterpriseAccount account; + + @ColorRes(R.color.font_red) + int fontRed; + + @ColorRes(R.color.font_orange) + int fontOragne; + + @AfterViews + void initEnterpriseAccountActivity() { + useToolbar(); + setActionBarTitle(""); + if (Build.VERSION.SDK_INT >= 21) { + getSupportActionBar().setElevation(0); + } + + updateUI(); + + loadDataFromNetwork(); + + if (GlobalData.isPrivateEnterprise()) { + findViewById(R.id.itemManagerLayout).setVisibility(View.GONE); + } + } + + @Override + protected void onRestart() { + super.onRestart(); + + loadDataFromNetwork(); + } + + private void loadDataFromNetwork() { + String host = String.format("%s/enterprise/%s", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + MyAsyncHttpClient.get(this, host, new MyJsonResponse(this) { + @Override + public void onMySuccess(JSONObject response) { + super.onMySuccess(response); + + account = new EnterpriseAccount(response.optJSONObject("data")); + Spanned countString; + + if (account.trial && !account.payed) { // 处于试用期 + int fontColor = account.remaindays > 5 ? fontOragne : fontRed; + countString = Global.createColorHtml("试用期剩余 ", String.valueOf(account.remaindays), " 天", fontColor); + } else { + if (account.payed) { + if (account.remaindays > 5) { // 付费期且未到期 + countString = Global.createColorHtml("账户余额:", account.balance, " 元", fontOragne); + } else if (account.remaindays > 0) { + countString = Global.createColorHtml("", "您的余额不足,请尽快订购", "", fontRed); + } else { // 付费期已到期 + String tip; + if (account.suspendedAt > 0) { // 已暂停 + tip = String.format("您的服务已暂停 %s 天,请订购后使用", account.suspendedToToday()); + } else { // 处于超时使用阶段 + tip = String.format("您的服务已超时使用 %s 天,请订购后使用", account.estimateDate()); + } + countString = Global.createColorHtml("", tip, "", fontRed); + } + } else { // 未付费而且试用期已过 + countString = Global.createColorHtml("", "您的试用期已结束,请订购后使用", "", fontRed); + } + } + + accountState.setText(countString); + } + + @Override + public void onMyFailure(JSONObject response) { + super.onMyFailure(response); + } + }); + } + + private void updateUI() { + ImageLoader.getInstance().displayImage(EnterpriseInfo.instance().getAvatar(), companyIcon, enterpriseIconOptions); + companyName.setText(EnterpriseInfo.instance().getName()); + } + + @Click + void itemProject() { + ManageProjectListActivity_.intent(this).start(); + } + + @Click + void itemMember() { + ManageMemberActivity_.intent(this).start(); + } + + @Click + void itemSupport() { + EnterpriseSupportActivity_.intent(this).start(); + } + + @Click + void itemManager() { + OrderMainActivity_.intent(this).account(account).start(); + } + + @OptionsItem + void action_setting() { + EnterpriseSettingActivity_.intent(this).startForResult(SETTING_REQUEST_CODE); + } + + @OnActivityResult(SETTING_REQUEST_CODE) + void OnSettingResult(int result) { + if (result == Activity.RESULT_OK) { + updateUI(); + } + } + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/EnterpriseMainSettingFragment.kt b/app/src/enterprise/java/net/coding/program/setting/EnterpriseMainSettingFragment.kt new file mode 100644 index 000000000..6663ff382 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/EnterpriseMainSettingFragment.kt @@ -0,0 +1,102 @@ +package net.coding.program.setting + +import android.view.View +import com.tbruyelle.rxpermissions2.RxPermissions +import kotlinx.android.synthetic.enterprise.enterprise_fragment_main_setting.* +import net.coding.program.R +import net.coding.program.common.GlobalData +import net.coding.program.common.model.EnterpriseInfo +import net.coding.program.common.ui.BaseFragment +import net.coding.program.common.util.PermissionUtil +import net.coding.program.compatible.CodingCompat +import net.coding.program.project.detail.file.LocalProjectFileActivity_ +import org.androidannotations.annotations.AfterViews +import org.androidannotations.annotations.Click +import org.androidannotations.annotations.EFragment + +/** + * Created by chenchao on 2017/1/5. + * 企业版的设置主界面 + */ +@EFragment(R.layout.enterprise_fragment_main_setting) +open class EnterpriseMainSettingFragment : BaseFragment() { + + @AfterViews + internal fun initEnterpriseMainSettingFragment() { + initMainSettingFragment() + + setToolbar("我的", R.id.toolbar) + var visible = View.GONE + if (EnterpriseInfo.instance().canManagerEnterprise()) { + visible = View.VISIBLE + companyName!!.text = EnterpriseInfo.instance().name + } + + itemManager!!.visibility = visible + itemManagerDivide!!.visibility = visible + + setHasOptionsMenu(false) + } + + @Click + fun itemManager() { + EnterpriseAccountActivity_.intent(this).start() + } + + private fun initMainSettingFragment() { + bindDataUserinfo() + } + + override fun onStart() { + super.onStart() + + loadUser() + bindDataUserinfo() + } + + private fun bindDataUserinfo() { + val me = GlobalData.sUserObject + iconfromNetwork(userIcon, me.avatar) + userIcon?.tag = me + userName.text = me.name + userGK.text = me.global_key + } + + private fun loadUser() { + } + + @Click + fun itemLocalFile() { + RxPermissions(activity!!) + .request(*PermissionUtil.STORAGE) + .subscribe { granted -> + if (granted!!) { + LocalProjectFileActivity_.intent(this).start() + } + } + } + + @Click + fun itemHelp() { + val url = "https://e.coding.net/help" + val title = getString(R.string.title_activity_help) + HelpActivity_.intent(this).url(url).title(title).start() + } + + @Click + fun userLayout() { + CodingCompat.instance().launchMyDetailActivity(activity) + } + + @Click + fun itemSetting() { + SettingActivity_.intent(this).start() + } + + @Click + fun itemAbout() { + AboutActivity_.intent(this).start() + } + + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/EnterpriseNameActivity.java b/app/src/enterprise/java/net/coding/program/setting/EnterpriseNameActivity.java new file mode 100644 index 000000000..db650eeaa --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/EnterpriseNameActivity.java @@ -0,0 +1,69 @@ +package net.coding.program.setting; + +import android.app.Activity; +import android.text.TextUtils; +import android.widget.EditText; + +import com.loopj.android.http.RequestParams; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.model.EnterpriseDetail; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.ui.BackActivity; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.OptionsItem; +import org.androidannotations.annotations.OptionsMenu; +import org.androidannotations.annotations.ViewById; +import org.json.JSONException; +import org.json.JSONObject; + +@EActivity(R.layout.activity_enterprise_name) +@OptionsMenu(R.menu.enterprise_edit_name_menu) +public class EnterpriseNameActivity extends BackActivity { + private static final String HOST_UPDATE_NAME = "HOST_UPDATE_NAME"; + public final String HOST_CURRENT = getHostCurrent(); + + public static String getHostCurrent() { + String host = String.format("%s/team/%s", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + return host + "/update"; + } + + @ViewById + EditText enterpriseNameEt; + + @AfterViews + void initView() { + setActionBarTitle(getString(R.string.enterprise_name)); + enterpriseNameEt.setText(EnterpriseInfo.instance().getName()); + } + + @OptionsItem + void action_edit_name() { + String name = enterpriseNameEt.getText().toString(); + if (!TextUtils.isEmpty(name)) { + RequestParams params = new RequestParams(); + params.put("name", name); + params.put("introduction", ""); + params.put("global_key", EnterpriseInfo.instance().getGlobalkey()); + postNetwork(HOST_CURRENT, params, HOST_UPDATE_NAME); + } + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(HOST_UPDATE_NAME)) { + if (code == 0) { + JSONObject dataObject = respanse.optJSONObject("data"); + EnterpriseDetail detail = new EnterpriseDetail(dataObject); + EnterpriseInfo.instance().update(this, detail); + setResult(Activity.RESULT_OK); + this.finish(); + } else { + showErrorMsg(code, respanse); + } + } + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/EnterpriseSettingActivity.java b/app/src/enterprise/java/net/coding/program/setting/EnterpriseSettingActivity.java new file mode 100644 index 000000000..0f7cbcab1 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/EnterpriseSettingActivity.java @@ -0,0 +1,212 @@ +package net.coding.program.setting; + +import android.app.Activity; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.MediaStore; +import android.support.v7.app.AlertDialog; +import android.widget.TextView; + +import com.loopj.android.http.RequestParams; +import com.nostra13.universalimageloader.core.ImageLoader; + +import net.coding.program.R; +import net.coding.program.common.CameraPhotoUtil; +import net.coding.program.common.Global; +import net.coding.program.common.ImageLoadTool; +import net.coding.program.common.model.EnterpriseDetail; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.common.util.FileUtil; +import net.coding.program.common.widget.FileProviderHelp; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.OnActivityResult; +import org.androidannotations.annotations.ViewById; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; + +import de.hdodenhof.circleimageview.CircleImageView; + +import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; +import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + +@EActivity(R.layout.activity_enterprise_setting) +public class EnterpriseSettingActivity extends BackActivity { + private static final int REQUEST_UPDATE_NAME = 1000; + private static final int RESULT_REQUEST_PHOTO = 1001; + private static final int RESULT_REQUEST_PHOTO_CROP = 1002; + + private static final String UPLOAD_IMG = "UPLOAD_IMG"; + private static final String PUT_IMG = "PUT_IMG"; + private static final String GET_IMG_DATA = "GET_IMG_DATA"; + + private final String uploadImgHost = getUploadImgHost(); + private final String updateImgHost = getUpdateHost(); + private final String getImgData = getImgHost(); + + @ViewById + CircleImageView enterpriseHead; + @ViewById + TextView enterpriseNameTv; + @ViewById + TextView personIp; + + private String getUploadImgHost() { + String host = String.format("%s/user", Global.HOST_API); + return host + "/avatar"; + } + + private String getUpdateHost() { + String host = String.format("%s/team/%s", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + return host + "/avatar"; + } + + private String getImgHost() { + String host = String.format("%s/team/%s", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + return host + "/get"; + } + + @AfterViews + void initView() { + setActionBarTitle(getString(R.string.enterprise_setting)); + ImageLoader.getInstance().displayImage(EnterpriseInfo.instance().getAvatar(), + enterpriseHead, EnterpriseAccountActivity.enterpriseIconOptions); + enterpriseNameTv.setText(EnterpriseInfo.instance().getName()); + personIp.setText(EnterpriseInfo.instance().getGlobalkey()); + } + + @Click + void enterpriseName() { + EnterpriseNameActivity_.intent(this).startForResult(REQUEST_UPDATE_NAME); + } + + @Click + void enterpriseHeadLayout() { + setIcon(); + } + + void setIcon() { + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle); + builder.setTitle("更换头像") + .setItems(R.array.camera_gallery, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == 0) { + camera(); + } else { + photo(); + } + } + }); + AlertDialog dialog = builder.create(); + dialog.show(); + } + + private Uri fileUri; + private Uri fileCropUri; + + private void camera() { + File tempFile = CameraPhotoUtil.getCacheFile(this); + fileUri = FileProviderHelp.getUriForFile(this, tempFile); + + Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0及以上 + intentFromCapture.addFlags(FLAG_GRANT_READ_URI_PERMISSION); + intentFromCapture.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION); + } + + startActivityForResult(intentFromCapture, RESULT_REQUEST_PHOTO); + } + + private void photo() { + Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + startActivityForResult(i, RESULT_REQUEST_PHOTO); + } + + @OnActivityResult(REQUEST_UPDATE_NAME) + void updateNameResult(int result) { + if (result == Activity.RESULT_OK) { + enterpriseNameTv.setText(EnterpriseInfo.instance().getName()); + setResult(Activity.RESULT_OK); + } + } + + @OnActivityResult(RESULT_REQUEST_PHOTO) + void updateHeadResult(int result, Intent data) { + if (result == Activity.RESULT_OK) { + if (data != null && data.getData() != null) { + fileUri = data.getData(); + } + + fileCropUri = CameraPhotoUtil.getOutputMediaFileUri(); + Global.startPhotoZoom(this, fileUri, fileCropUri, RESULT_REQUEST_PHOTO_CROP); + } + } + + @OnActivityResult(RESULT_REQUEST_PHOTO_CROP) + void updatePhotoCropResult(int result, Intent data) { + if (result == Activity.RESULT_OK) { + try { + String filePath = FileUtil.getPath(this, fileCropUri); + RequestParams params = new RequestParams(); + params.put("images.jpg", new File(filePath)); + postNetwork(uploadImgHost, params, UPLOAD_IMG); + showDialogLoading(); + } catch (Exception e) { + Global.errorLog(e); + } + } + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(UPLOAD_IMG)) { + if (code == 0) { + String url = respanse.optString("data"); + putImg(url); + } else { + showErrorMsg(code, respanse); + hideProgressDialog(); + } + } else if (tag.equals(PUT_IMG)) { + hideProgressDialog(); + if (code == 0) { + getImgData(); + } else { + showErrorMsg(code, respanse); + hideProgressDialog(); + } + } else if (tag.equals(GET_IMG_DATA)) { + hideProgressDialog(); + if (code == 0) { + JSONObject dataObject = respanse.optJSONObject("data"); + EnterpriseDetail detail = new EnterpriseDetail(dataObject); + EnterpriseInfo.instance().update(this, detail); + ImageLoader.getInstance().displayImage(EnterpriseInfo.instance().getAvatar(), enterpriseHead, ImageLoadTool.options); + } else { + showErrorMsg(code, respanse); + } + } + + setResult(Activity.RESULT_OK); + } + + private void putImg(String url) { + RequestParams params = new RequestParams(); + params.put("url", url); + putNetwork(updateImgHost, params, PUT_IMG); + } + + public void getImgData() { + getNetwork(getImgHost(), GET_IMG_DATA); + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/EnterpriseSupportActivity.kt b/app/src/enterprise/java/net/coding/program/setting/EnterpriseSupportActivity.kt new file mode 100644 index 000000000..5eca84aa7 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/EnterpriseSupportActivity.kt @@ -0,0 +1,56 @@ +package net.coding.program.setting + +import android.app.Activity +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.net.Uri +import net.coding.program.R +import net.coding.program.common.Global +import net.coding.program.common.ui.BackActivity +import org.androidannotations.annotations.Click +import org.androidannotations.annotations.EActivity + +@EActivity(R.layout.activity_enterprise_support) +open class EnterpriseSupportActivity : BackActivity() { + + @Click + fun itemPhone() { + dialPhoneNumber(this, "400-930-9163") + } + + @Click + fun itemEmail() { + composeEmail(this, arrayOf("enterprise@coding.net")) + } + + @Click + fun itemQQ() = try { + val uri1 = "mqqwpa://im/chat?chat_type=wpa&uin=2847276903&version=1" + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(uri1))) + } catch (e: Exception) { + showDialog("已复制 QQ 号到剪贴板", + object : DialogInterface.OnClickListener { + override fun onClick(dialog: DialogInterface?, which: Int) { + Global.copy(this@EnterpriseSupportActivity, "2847276903") + } + }) + } + + fun dialPhoneNumber(activity: Activity, phoneNumber: String) { + val intent = Intent(Intent.ACTION_DIAL) + intent.data = Uri.parse("tel:$phoneNumber") + if (intent.resolveActivity(activity.packageManager) != null) { + activity.startActivity(intent) + } + } + + fun composeEmail(context: Context, addresses: Array ) { + val intent = Intent(Intent.ACTION_SENDTO) + intent.data = Uri.parse("mailto:") // only email apps should handle this + intent.putExtra(Intent.EXTRA_EMAIL, addresses) + if (intent.resolveActivity(context.packageManager) != null) { + context.startActivity(intent) + } + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/ManageMemberActivity.java b/app/src/enterprise/java/net/coding/program/setting/ManageMemberActivity.java new file mode 100644 index 000000000..7984161c6 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/ManageMemberActivity.java @@ -0,0 +1,349 @@ +package net.coding.program.setting; + +import android.os.Handler; +import android.os.Message; +import android.support.annotation.NonNull; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerView; +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerviewViewHolder; +import com.marshalchen.ultimaterecyclerview.quickAdapter.easyRegularAdapter; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.GlobalData; +import net.coding.program.common.SimpleSHA1; +import net.coding.program.common.WeakRefHander; +import net.coding.program.common.model.AccountInfo; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.model.team.TeamMember; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.common.ui.shadow.RecyclerViewSpace; +import net.coding.program.common.umeng.UmengEvent; +import net.coding.program.login.auth.AuthInfo; +import net.coding.program.login.auth.TotpClock; +import net.coding.program.network.BaseHttpObserver; +import net.coding.program.network.HttpObserver; +import net.coding.program.network.Network; +import net.coding.program.network.constant.MemberAuthority; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.OnActivityResult; +import org.androidannotations.annotations.ViewById; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +@EActivity(R.layout.activity_manage_member) +public class ManageMemberActivity extends BackActivity implements Handler.Callback { + + private static final String TAG_PROJECT = "TAG_PROJECT"; + + private static final int RESULT_SET_ENTERPRISE_ROLE = 1; + private static final int RESULT_REMOVE_MEMBER = 2; + + @ViewById + UltimateRecyclerView listView; + + MemberAdapter adapter; + + ArrayList listData = new ArrayList<>(); + + @AfterViews + void initManageMemberActivity() { + listView.setLayoutManager(new LinearLayoutManager(this)); + listView.addItemDecoration(new RecyclerViewSpace(this)); + listView.setEmptyView(R.layout.fragment_enterprise_project_empty, R.layout.fragment_enterprise_project_empty); + + adapter = new MemberAdapter(listData); + listView.setAdapter(adapter); + listView.setDefaultOnRefreshListener(() -> onRefresh()); + listView.enableDefaultSwipeRefresh(true); + + onRefresh(); + + hander2fa = new WeakRefHander(this, 100); + } + + private void onRefresh() { + String host = String.format("%s/team/%s/members", Global.HOST_API, GlobalData.getEnterpriseGK()); + getNetwork(host, TAG_PROJECT); + } + + protected class MemberAdapter extends easyRegularAdapter { + + public MemberAdapter(List list) { + super(list); + } + + @Override + protected int getNormalLayoutResId() { + return R.layout.enterprise_manage_member_list_item; + } + + @Override + protected ProjectHolder newViewHolder(View view) { + ProjectHolder holder = new ProjectHolder(view); + holder.actionMore.setOnClickListener(clickItemMore); + holder.rootLayout.setOnClickListener(clickItemMore); + holder.rootLayout.setOnLongClickListener(longClickItem); + return holder; + } + + @Override + protected void withBindHolder(ProjectHolder holder, TeamMember data, int position) { + TeamMember item = getItem(position); + holder.name.setText(item.user.name); + holder.joinTime.setText(String.format("加入时间:%s", Global.mDateYMDHH.format(data.updatedat))); + holder.rootLayout.setTag(item); + holder.actionMore.setTag(item); + + MemberAuthority memberType = item.getType(); + int iconRes = memberType.getIcon(); + holder.name.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconRes, 0); + iconfromNetwork(holder.image, item.user.avatar); + } + + @Override + public ProjectHolder newHeaderHolder(View view) { + return new ProjectHolder(view, true); + } + + @Override + public ProjectHolder newFooterHolder(View view) { + return new ProjectHolder(view, true); + } + } + + private View.OnClickListener clickItemMore = this::actionMore; + + private View.OnLongClickListener longClickItem = v -> { + actionMore(v); + return true; + }; + + private void actionMore(View v) { + TeamMember user = (TeamMember) v.getTag(); + if ((user.getType() == MemberAuthority.ower)) { + new AlertDialog.Builder(this, R.style.MyAlertDialogStyle) + .setItems(R.array.manager_member_to_owner, ((dialog, which) -> { + if (which == 0) { + actionModifyProjectRole(user); + } + })) + .show(); + } else if (EnterpriseInfo.instance().isOwner()) { + new AlertDialog.Builder(this, R.style.MyAlertDialogStyle) + .setItems(R.array.manager_member_by_owner, ((dialog, which) -> { + if (which == 0) { + actionModifyEnterpriseRole(user); + } else if (which == 1) { + actionModifyProjectRole(user); + } else if (which == 2) { + actionRemove(user); + } + })) + .show(); + } else { + new AlertDialog.Builder(this, R.style.MyAlertDialogStyle) + .setItems(R.array.manager_member_by_manager, ((dialog, which) -> { + if (which == 0) { + actionModifyProjectRole(user); + } else if (which == 1) { + actionRemove(user); + } + })) + .show(); + } + } + + public static class ProjectHolder extends UltimateRecyclerviewViewHolder { + + public TextView name; + public TextView joinTime; + public ImageView image; + public View rootLayout; + public View actionMore; + + public ProjectHolder(View view, boolean isHeader) { + super(view); + } + + public ProjectHolder(View view) { + super(view); + rootLayout = view; + name = (TextView) view.findViewById(R.id.name); + joinTime = (TextView) view.findViewById(R.id.joinTime); + image = (ImageView) view.findViewById(R.id.icon); + actionMore = view.findViewById(R.id.actionMore); + } + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_PROJECT)) { + if (code == 0) { + listData.clear(); + JSONArray array = respanse.optJSONArray("data"); + for (int i = 0; i < array.length(); ++i) { + listData.add(new TeamMember(array.optJSONObject(i))); + } + + adapter.notifyDataSetChanged(); + } else { + showErrorMsg(code, respanse); + } + } + } + + Handler hander2fa; + private EditText edit2fa; + + private void actionRemove(TeamMember user) { + Network.getRetrofit(this) + .need2FA() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new HttpObserver (ManageMemberActivity.this) { + @Override + public void onSuccess(String data) { + if (data.equals("totp")) { + actionRemove2FA(user); + } else { // password + actionRemoveNormal(user); + } + } + }); + } + + private void actionRemove2FA(TeamMember user) { + hander2fa.sendEmptyMessage(0); + LayoutInflater factory = LayoutInflater.from(this); + final View textEntryView = factory.inflate(R.layout.dialog_delete_project_2fa, null); + edit2fa = (EditText) textEntryView.findViewById(R.id.edit1); + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle); + AlertDialog dialog = builder + .setView(textEntryView) + .setPositiveButton("确定", (dialog1, whichButton) -> { + String editStr1 = edit2fa.getText().toString().trim(); + if (TextUtils.isEmpty(editStr1)) { + Toast.makeText(ManageMemberActivity.this, "密码不能为空", Toast.LENGTH_LONG).show(); + return; + } + actionDelete2FA(user, editStr1); + }) + .setNegativeButton("取消", null) + .show(); + + dialog.setOnDismissListener(dialog1 -> { + hander2fa.removeMessages(0); + edit2fa = null; + }); + } + + private void actionRemoveNormal(TeamMember user) { + LayoutInflater factory = LayoutInflater.from(this); + final View textEntryView = factory.inflate(R.layout.dialog_delete_project, null); + edit2fa = textEntryView.findViewById(R.id.edit1); + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle); + AlertDialog dialog = builder + .setView(textEntryView) + .setPositiveButton("确定", (dialog1, whichButton) -> { + String editStr1 = edit2fa.getText().toString().trim(); + if (TextUtils.isEmpty(editStr1)) { + Toast.makeText(ManageMemberActivity.this, "密码不能为空", Toast.LENGTH_LONG).show(); + return; + } + actionDelete2FA(user, SimpleSHA1.sha1(editStr1)); + }) + .setNegativeButton("取消", null) + .show(); + + dialog.setOnDismissListener(dialog1 -> { + hander2fa.removeMessages(0); + edit2fa = null; + }); + } + + private void actionDelete2FA(TeamMember user, String code) { + Network.getRetrofit(this) + .removeEnterpriseMember(GlobalData.getEnterpriseGK(), user.user.global_key, code) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new BaseHttpObserver(this) { + @Override + public void onSuccess() { + super.onSuccess(); + umengEvent(UmengEvent.E_USER_CENTER, "删除企业成员"); + showProgressBar(false); + + listData.remove(user); + adapter.notifyDataSetChanged(); + } + + @Override + public void onFail(int errorCode, @NonNull String error) { + super.onFail(errorCode, error); + showProgressBar(false); + } + }); + + showProgressBar(true); + } + + @Override + public boolean handleMessage(Message msg) { + if (edit2fa != null) { + String secret = AccountInfo.loadAuth(this, GlobalData.sUserObject.global_key); + if (secret.isEmpty()) { + return true; + } + + String code2FA = new AuthInfo(secret, new TotpClock(this)).getCode(); + edit2fa.setText(code2FA); + } + return true; + } + + private void actionModifyProjectRole(TeamMember user) { + CommonPickProjectActivity_.intent(this) + .member(user) + .start(); + } + + private void actionModifyEnterpriseRole(TeamMember user) { + SetEnterpriseAuthorityActivity_.intent(this) + .globayKey(user.user.global_key) + .authority(user.getType()) + .startForResult(RESULT_SET_ENTERPRISE_ROLE); + } + + @OnActivityResult(RESULT_SET_ENTERPRISE_ROLE) + void onResultSetEnterpriseRole(int resultCode, @OnActivityResult.Extra int intentData, + @OnActivityResult.Extra String intentData1) { + if (resultCode == RESULT_OK) { + for (TeamMember item : listData) { + if (item.user.global_key.equals(intentData1)) { + item.role = intentData; + break; + } + } + } + } + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/ManageProjectListActivity.java b/app/src/enterprise/java/net/coding/program/setting/ManageProjectListActivity.java new file mode 100644 index 000000000..cfd279074 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/ManageProjectListActivity.java @@ -0,0 +1,367 @@ +package net.coding.program.setting; + +import android.os.Handler; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerviewViewHolder; +import com.marshalchen.ultimaterecyclerview.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; + +import net.coding.program.R; +import net.coding.program.common.GlobalData; +import net.coding.program.common.ImageLoadTool; +import net.coding.program.common.SimpleSHA1; +import net.coding.program.common.WeakRefHander; +import net.coding.program.common.model.AccountInfo; +import net.coding.program.common.model.ProjectObject; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.common.ui.shadow.RecyclerViewSpace; +import net.coding.program.common.umeng.UmengEvent; +import net.coding.program.common.widget.CommonAdapter; +import net.coding.program.common.widget.CommonListView; +import net.coding.program.login.auth.AuthInfo; +import net.coding.program.login.auth.TotpClock; +import net.coding.program.network.BaseHttpObserver; +import net.coding.program.network.HttpObserver; +import net.coding.program.network.Network; +import net.coding.program.project.EventProjectModify; +import net.coding.program.project.ProjectHomeActivity_; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +@EActivity(R.layout.common_simple_listview) +public class ManageProjectListActivity extends BackActivity { + + @ViewById + CommonListView listView; + + ProjectAdapter adapter; + + ArrayList listData = new ArrayList<>(); + private List listJoinData = new ArrayList<>(); + + Handler hander2fa; + private EditText edit2fa; + + @AfterViews + void initManageProjectListActivity() { + listView.setLayoutManager(new LinearLayoutManager(this)); + listView.addItemDecoration(new RecyclerViewSpace(this)); + + adapter = new ProjectAdapter(listData); + StickyRecyclerHeadersDecoration stickyHeader = new StickyRecyclerHeadersDecoration(adapter); + listView.addItemDecoration(stickyHeader); + + listView.setAdapter(adapter); + listView.setDefaultOnRefreshListener(() -> onRefresh()); + listView.enableDefaultSwipeRefresh(true); + + onRefresh(); + + hander2fa = new WeakRefHander(msg -> { + if (edit2fa != null) { + String secret = AccountInfo.loadAuth(getApplicationContext(), GlobalData.sUserObject.global_key); + if (secret.isEmpty()) { + return true; + } + + String code2FA = new AuthInfo(secret, new TotpClock(getApplicationContext())).getCode(); + edit2fa.setText(code2FA); + } + return true; + }, 100); + + } + + private void onRefresh() { + Network.getRetrofit(this) + .getProjects() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .flatMap(listHttpResult -> { + if (listHttpResult == null) { + return null; + } + listJoinData.clear(); + listJoinData.addAll(listHttpResult.data.list); + return Network.getRetrofit(ManageProjectListActivity.this, listView) + .getManagerProjects(GlobalData.getEnterpriseGK()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + }) + .subscribe(new HttpObserver >(this, listView) { + @Override + public void onSuccess(List
data) { + super.onSuccess(data); + listData.clear(); + + int joinedPos = 0; + for (ProjectObject item : data) { + boolean find = false; + for (ProjectObject join : listJoinData) { + if (join.id == item.id) { + find = true; + join.memberNum = item.memberNum; + listData.add(joinedPos++, join); + break; + } + } + + if (!find) { + listData.add(item); + } + } + } + }); + } + + public static class DynamicSectionHolder extends UltimateRecyclerviewViewHolder { + + public static final int LAYOUT = R.layout.fragment_project_dynamic_list_head; + + public TextView head; + + public DynamicSectionHolder(View v) { + super(v); + head = (TextView) v.findViewById(R.id.head); + } + } + + protected class ProjectAdapter extends CommonAdapter { + + public ProjectAdapter(List list) { + super(list); + } + + @Override + protected int getNormalLayoutResId() { + return R.layout.enterprise_manage_project_list_item; + } + + @Override + protected ProjectHolder newViewHolder(View view) { + ProjectHolder holder = new ProjectHolder(view); + holder.rootLayout.setOnClickListener(clickItem); + holder.rootLayout.setOnLongClickListener(longClickItem); + holder.actionMore.setOnClickListener(clickItemMore); + return holder; + } + + @Override + protected void withBindHolder(ProjectHolder holder, ProjectObject data, int position) { + ProjectObject item = getItem(position); + holder.name.setText(item.name); + holder.memberCount.setText(String.format("%s 人", data.memberNum)); + holder.rootLayout.setTag(item); + holder.actionMore.setTag(item); + iconfromNetwork(holder.image, item.icon, ImageLoadTool.optionsRounded2); + } + + @Override + public long generateHeaderId(int i) { + if (getItem(i).isJoined()) { + return 0; + } else { + return 1; + } + } + + @Override + public ProjectHolder newHeaderHolder(View view) { + return new ProjectHolder(view, true); + } + + @Override + public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder, int pos) { + DynamicSectionHolder holder = (DynamicSectionHolder) viewHolder; + if (generateHeaderId(pos) == 0) { + holder.head.setText("我参与的"); + } else { + holder.head.setText("我未参与的"); + } + } + + @Override + public UltimateRecyclerviewViewHolder onCreateHeaderViewHolder(ViewGroup parent) { + View v = LayoutInflater.from(parent.getContext()).inflate(DynamicSectionHolder.LAYOUT, parent, false); + return new DynamicSectionHolder(v); + } + + @Override + public boolean hasHeaderView() { + return super.hasHeaderView(); + } + + @Override + public long getHeaderId(int position) { + return super.getHeaderId(position); + } + + @Override + public ProjectHolder newFooterHolder(View view) { + return new ProjectHolder(view, true); + } + } + + public static class ProjectHolder extends UltimateRecyclerviewViewHolder { + + public TextView name; + public TextView memberCount; + public ImageView image; + public View rootLayout; + public View actionMore; + + public ProjectHolder(View view, boolean isHeader) { + super(view); + } + + public ProjectHolder(View view) { + super(view); + rootLayout = view; + name = (TextView) view.findViewById(R.id.name); + memberCount = (TextView) view.findViewById(R.id.memberCount); + image = (ImageView) view.findViewById(R.id.icon); + actionMore = view.findViewById(R.id.actionMore); + } + } + + private View.OnClickListener clickItem = v -> { + Object object = v.getTag(); + if (object instanceof ProjectObject) { + ProjectObject item = (ProjectObject) object; + + if (item.isJoined()) { + ProjectHomeActivity_.intent(this) + .mProjectObject(item) + .start(); + } else { + showMiddleToast("无权进入项目"); + } + } + }; + + private View.OnLongClickListener longClickItem = v -> { + actionMore(v); + + return true; + }; + + private void actionMore(View v) { + ProjectObject project = (ProjectObject) v.getTag(); + new AlertDialog.Builder(v.getContext(), R.style.MyAlertDialogStyle) + .setItems(R.array.manager_project_item, (dialog, which) -> { + if (which == 0) { + Network.getRetrofit(ManageProjectListActivity.this) + .need2FA() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new HttpObserver (ManageProjectListActivity.this) { + @Override + public void onSuccess(String data) { + if (data.equals("totp")) { + showDeleteDialog2fa(project); + } else { // password + showDeleteDialog(project); + } + } + }); + } + }) + .show(); + } + + private View.OnClickListener clickItemMore = this::actionMore; + + private void showDeleteDialog2fa(ProjectObject project) { + hander2fa.sendEmptyMessage(0); + LayoutInflater factory = LayoutInflater.from(this); + final View textEntryView = factory.inflate(R.layout.dialog_delete_project_2fa, null); + edit2fa = (EditText) textEntryView.findViewById(R.id.edit1); + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle); + AlertDialog dialog = builder + .setView(textEntryView) + .setPositiveButton("确定", (dialog1, whichButton) -> { + String editStr1 = edit2fa.getText().toString().trim(); + if (TextUtils.isEmpty(editStr1)) { + showMiddleToast("验证码不能为空"); + return; + } + actionDelete2FA(project, editStr1); + }) + .setNegativeButton("取消", null) + .show(); + + dialog.setOnDismissListener(dialog1 -> { + hander2fa.removeMessages(0); + edit2fa = null; + }); + } + + private void showDeleteDialog(ProjectObject project) { + LayoutInflater factory = LayoutInflater.from(this); + final View textEntryView = factory.inflate(R.layout.dialog_delete_project, null); + final EditText edit1 = (EditText) textEntryView.findViewById(R.id.edit1); + new AlertDialog.Builder(this, R.style.MyAlertDialogStyle) + .setTitle("需要验证密码") + .setView(textEntryView) + .setPositiveButton("确定", (dialog1, whichButton) -> { + String editStr1 = edit1.getText().toString().trim(); + if (TextUtils.isEmpty(editStr1)) { + showMiddleToast("密码不能为空"); + return; + } + + actionDelete2FA(project, SimpleSHA1.sha1(editStr1)); + }) + .setNegativeButton("取消", null) + .show(); + } + + + private void actionDelete2FA(final ProjectObject project, String password) { + Network.getRetrofit(this) + .deleteProject(project.getV2PathById(), password) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new BaseHttpObserver(this) { + @Override + public void onSuccess() { + super.onSuccess(); + + umengEvent(UmengEvent.E_USER_CENTER, "删除企业项目"); + + showButtomToast("删除成功"); + listData.remove(project); + adapter.notifyDataSetChanged(); + } + }); + } + + @Override + protected boolean userEventBus() { + return true; + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEventProjectModify(EventProjectModify event) { + onRefresh(); + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/SetEnterpriseAuthorityActivity.java b/app/src/enterprise/java/net/coding/program/setting/SetEnterpriseAuthorityActivity.java new file mode 100644 index 000000000..7ece270e9 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/SetEnterpriseAuthorityActivity.java @@ -0,0 +1,92 @@ +package net.coding.program.setting; + +import android.content.Intent; +import android.support.annotation.NonNull; + +import net.coding.program.R; +import net.coding.program.common.GlobalData; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.common.umeng.UmengEvent; +import net.coding.program.network.BaseHttpObserver; +import net.coding.program.network.Network; +import net.coding.program.network.constant.MemberAuthority; +import net.coding.program.project.detail.DropdownListItemView; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.ViewById; + +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +@EActivity(R.layout.activity_set_enterprise_authority) +public class SetEnterpriseAuthorityActivity extends BackActivity { + + @Extra + MemberAuthority authority; + + @Extra + String globayKey; + + @ViewById + DropdownListItemView enterprseManager, enterpriseMember; + + @AfterViews + void initMemberAuthorityActivity() { + enterprseManager.setText("管理员"); + enterpriseMember.setText("普通成员"); + + enterprseManager.setChecked(false); + enterpriseMember.setChecked(false); + + switch (authority) { + case manager: + enterprseManager.setChecked(true); + break; + case member: + enterpriseMember.setChecked(true); + break; + } + } + + @Click + void enterprseManager() { + modifyAuthority(MemberAuthority.manager.getType()); + } + + @Click + void enterpriseMember() { + modifyAuthority(MemberAuthority.member.getType()); + } + + private void modifyAuthority(int id) { + Network.getRetrofit(this) + .setEnterpriseRole(GlobalData.getEnterpriseGK(), globayKey, id) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new BaseHttpObserver(this) { + @Override + public void onSuccess() { + super.onSuccess(); + umengEvent(UmengEvent.E_USER_CENTER, "企业角色设置"); + showProgressBar(false); + + Intent intent = new Intent(); + intent.putExtra("intentData", id); + intent.putExtra("intentData1", globayKey); + setResult(RESULT_OK, intent); + + finish(); + } + + @Override + public void onFail(int errorCode, @NonNull String error) { + super.onFail(errorCode, error); + showProgressBar(false); + } + }); + showProgressBar(true); + } +} diff --git a/app/src/enterprise/java/net/coding/program/setting/order/BillingListFragment.java b/app/src/enterprise/java/net/coding/program/setting/order/BillingListFragment.java new file mode 100644 index 000000000..dbf1e7a25 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/order/BillingListFragment.java @@ -0,0 +1,116 @@ +package net.coding.program.setting.order; + + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerView; +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerviewViewHolder; +import com.marshalchen.ultimaterecyclerview.quickAdapter.easyRegularAdapter; + +import net.coding.program.R; +import net.coding.program.common.event.EventRefresh; +import net.coding.program.common.model.payed.Billing; +import net.coding.program.common.ui.BaseFragment; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EFragment; +import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +@EFragment(R.layout.common_ul_recyclerview) +public class BillingListFragment extends BaseFragment { + + @ViewById + UltimateRecyclerView listView; + + MyAdapter myAdapter; + + @AfterViews + void initBillingListFragment() { + OrderMainActivity activity = (OrderMainActivity) getActivity(); + + RecyclerView.LayoutManager manager = new LinearLayoutManager(getActivity()); + listView.setLayoutManager(manager); + myAdapter = new MyAdapter(activity.getBillingList()); + listView.setAdapter(myAdapter); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + EventBus.getDefault().register(this); + } + + @Override + public void onDetach() { + super.onDetach(); + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEventRefresh(EventRefresh event) { + if (event.refresh) { + myAdapter.notifyDataSetChanged(); + } + } + + protected class MyAdapter extends easyRegularAdapter { + + public MyAdapter(List list) { + super(list); + } + + @Override + protected int getNormalLayoutResId() { + return R.layout.billing_item; + } + + @Override + protected BillingListFragment.ViewHolder newViewHolder(View view) { + return new BillingListFragment.ViewHolder(view); + } + + @Override + protected void withBindHolder(BillingListFragment.ViewHolder holder, Billing data, int position) { + holder.title.setText(data.getTitle()); + holder.count.setText(String.format("%s 人", data.userCount)); + holder.price.setText(String.format("¥ %s", data.price)); + holder.time.setText(data.getTime()); + + if (position == source.size() - 1) { + holder.nextTopDivide.setVisibility(View.GONE); + } else { + holder.nextTopDivide.setVisibility(View.VISIBLE); + } + } + } + + class ViewHolder extends UltimateRecyclerviewViewHolder { + + private TextView title; + private TextView count; + private TextView price; + private TextView time; + private View nextTopDivide; + + public ViewHolder(View view) { + super(view); + + title = (TextView) view.findViewById(R.id.title); + count = (TextView) view.findViewById(R.id.count); + price = (TextView) view.findViewById(R.id.price); + time = (TextView) view.findViewById(R.id.time); + nextTopDivide = view.findViewById(R.id.nextTopDivide); + } + } + + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/order/EmptyFragment.java b/app/src/enterprise/java/net/coding/program/setting/order/EmptyFragment.java new file mode 100644 index 000000000..f801ce332 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/order/EmptyFragment.java @@ -0,0 +1,13 @@ +package net.coding.program.setting.order; + + +import net.coding.program.R; +import net.coding.program.common.ui.BaseFragment; + +import org.androidannotations.annotations.EFragment; + +@EFragment(R.layout.order_empty) +public class EmptyFragment extends BaseFragment { + + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/order/OrderListFragment.java b/app/src/enterprise/java/net/coding/program/setting/order/OrderListFragment.java new file mode 100644 index 000000000..d970436e2 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/order/OrderListFragment.java @@ -0,0 +1,129 @@ +package net.coding.program.setting.order; + + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerView; +import com.marshalchen.ultimaterecyclerview.UltimateRecyclerviewViewHolder; +import com.marshalchen.ultimaterecyclerview.quickAdapter.easyRegularAdapter; + +import net.coding.program.R; +import net.coding.program.common.event.EventRefresh; +import net.coding.program.common.model.payed.Order; +import net.coding.program.common.ui.BaseFragment; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EFragment; +import org.androidannotations.annotations.ViewById; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +@EFragment(R.layout.common_ul_recyclerview) +public class OrderListFragment extends BaseFragment { + + @ViewById + UltimateRecyclerView listView; + + MyAdapter adapter; + + @AfterViews + void initOrderListFragment() { + OrderMainActivity activity = (OrderMainActivity) getActivity(); + + RecyclerView.LayoutManager manager = new LinearLayoutManager(getActivity()); + listView.setLayoutManager(manager); + + adapter = new MyAdapter(activity.getOrderList()); + listView.setAdapter(adapter); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + EventBus.getDefault().register(this); + } + + @Override + public void onDetach() { + super.onDetach(); + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEventRefresh(EventRefresh event) { + if (event.refresh) { + adapter.notifyDataSetChanged(); + } + } + + protected class MyAdapter extends easyRegularAdapter { + + public MyAdapter(List list) { + super(list); + } + + @Override + protected int getNormalLayoutResId() { + return R.layout.order_item; + } + + @Override + protected ViewHolder newViewHolder(View view) { + return new ViewHolder(view); + } + + @Override + protected void withBindHolder(ViewHolder holder, Order data, int position) { + + holder.title.setText(data.getAction()); + holder.style.setText(data.statusString); + holder.style.setTextColor(data.statusColor); + holder.id.setText(data.number); + holder.user.setText(data.creatorName); + holder.time.setText(data.getTime()); + + if (position == source.size() - 1) { + holder.nextTopDivide.setVisibility(View.GONE); + } else { + holder.nextTopDivide.setVisibility(View.VISIBLE); + } + } + } + + class ViewHolder extends UltimateRecyclerviewViewHolder { + + private TextView title; + private TextView style; + private View divideLine; + private TextView orderId; + private TextView orderUser; + private TextView orderTime; + private TextView id; + private TextView user; + private TextView time; + + private View nextTopDivide; + + public ViewHolder(View view) { + super(view); + title = (TextView) view.findViewById(R.id.title); + style = (TextView) view.findViewById(R.id.style); + divideLine = (View) view.findViewById(R.id.divideLine); + orderId = (TextView) view.findViewById(R.id.orderId); + orderUser = (TextView) view.findViewById(R.id.orderUser); + orderTime = (TextView) view.findViewById(R.id.orderTime); + id = (TextView) view.findViewById(R.id.id); + user = (TextView) view.findViewById(R.id.user); + time = (TextView) view.findViewById(R.id.time); + nextTopDivide = view.findViewById(R.id.nextTopDivide); + } + } + +} diff --git a/app/src/enterprise/java/net/coding/program/setting/order/OrderMainActivity.java b/app/src/enterprise/java/net/coding/program/setting/order/OrderMainActivity.java new file mode 100644 index 000000000..48eedc129 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/setting/order/OrderMainActivity.java @@ -0,0 +1,334 @@ +package net.coding.program.setting.order; + +import android.content.Context; +import android.support.design.widget.AppBarLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewPager; +import android.support.v4.widget.SwipeRefreshLayout; +import android.text.Spanned; +import android.text.SpannedString; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.orhanobut.logger.Logger; + +import net.coding.program.R; +import net.coding.program.common.CodingColor; +import net.coding.program.common.Global; +import net.coding.program.common.event.EventRefresh; +import net.coding.program.common.model.EnterpriseAccount; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.model.payed.Billing; +import net.coding.program.common.model.payed.Order; +import net.coding.program.common.ui.BackActivity; +import net.coding.program.third.WechatTab; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.ViewById; +import org.androidannotations.annotations.res.ColorRes; +import org.greenrobot.eventbus.EventBus; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; + +@EActivity(R.layout.activity_order_main) +public class OrderMainActivity extends BackActivity { + + private static final String TAG_ORDERS = "TAG_ORDERS"; + private static final String TAG_BILLINGS = "TAG_BILLINGS"; + private static final String TAG_INFO = "TAG_INFO"; + + @Extra + EnterpriseAccount account; + + @ViewById + SwipeRefreshLayout swipeRefreshLayout; + + @ViewById + AppBarLayout appbarLayout; + + @ViewById + TextView topWarn, balanceTitle, balanceContent, balanceTip; + + @ViewById + View topTip; + + @ViewById + ViewGroup containerHeader; + + @ViewById + ViewGroup rootLayout; + + @ViewById + ViewPager viewPager; + + @ColorRes(R.color.font_orange) + int fontOragne; + + @ColorRes(R.color.font_red) + int fontRed; + + @ViewById + ImageView closeTipButton; + + private ArrayList orderList = new ArrayList<>(); + private ArrayList billingList = new ArrayList<>(); + + AppBarLayout.OnOffsetChangedListener appbarOffsetChange = new AppBarLayout.OnOffsetChangedListener() { + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + Logger.d("offset " + verticalOffset); + swipeRefreshLayout.setEnabled(verticalOffset >= 0); + } + }; + + @AfterViews + void initOrderMainActivity() { + closeTipButton.setImageDrawable(Global.tintDrawable( + getResources().getDrawable(R.drawable.delete_edit_login_black), CodingColor.fontYellow)); + + initHeader(); + + swipeRefreshLayout.setColorSchemeResources(R.color.font_green); + swipeRefreshLayout.setOnRefreshListener(() -> { + String host = String.format("%s/enterprise/%s", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + getNetwork(host, TAG_INFO); + + }); + } + + @Override + public void onResume() { + super.onResume(); + appbarLayout.addOnOffsetChangedListener(appbarOffsetChange); + } + + @Override + public void onPause() { + super.onPause(); + appbarLayout.addOnOffsetChangedListener(appbarOffsetChange); + } + + private void initHeader() { + SimpleDateFormat df = new SimpleDateFormat("yyyy 年 MM月 dd日"); + String timeString = df.format(Long.valueOf(account.estimateDate)); + SpannedString empty = new SpannedString(""); + + boolean showTip = false; + Spanned warnString = empty; + Spanned balanceTitleString = empty; + Spanned balanceContentString = empty; + String balanceTipString = ""; + + if (account.trial && !account.payed) { // 处于试用期 + warnString = Global.createColorHtml("您正在免费试用 CODING 企业服务", fontOragne); + balanceTipString = String.format("预计可使用至 %s,剩余 %s 天", timeString, account.remaindays); + + if (account.payed) { // 试用期且付过费 + balanceTitleString = new SpannedString("账户余额(元)"); + balanceContentString = Global.createColorHtml(account.balance, fontOragne); + showOrderAndRecord(true); + } else { + showOrderAndRecord(false); + } + + } else { + if (account.payed) { + if (account.remaindays > 0) { // 付费期且未到期 + showTip = false; + if (account.remaindays > 5) { + } else { + warnString = Global.createColorHtml("您的账户余额不足,请尽快订购", fontRed); + } + + balanceTitleString = new SpannedString("账户余额(元)"); + balanceContentString = Global.createColorHtml(account.balance, fontOragne); + balanceTipString = String.format("预计可使用至 %s,剩余 %s 天", df.format(account.estimateDate), account.remaindays); + + showOrderAndRecord(true); + + } else { // 付费期已到期 + showTip = true; + warnString = Global.createColorHtml("您的服务已过期,请订购后使用", fontRed); + balanceTitleString = new SpannedString("已透支金额(元)"); + balanceContentString = Global.createColorHtml(account.balance, fontRed); + + if (account.suspendedAt > 0) { // 已暂停 + balanceTipString = String.format("服务已暂停 %s 天", account.suspendedToToday()); + showOrderAndRecord(false); + } else { // 处于超时使用阶段 + balanceTipString = String.format("过期时间为 %s,已超时使用 %s 天", df.format(account.estimateDate), account.estimateDate()); + showOrderAndRecord(true); + } + } + } else { // 未付费而且试用期已过 + showTip = true; + warnString = Global.createColorHtml("您的试用期已结束,请订购后使用", fontRed); + int suspand = account.suspendedToToday(); + balanceTipString = String.format("服务已暂停 %s 天", suspand); + + showOrderAndRecord(false); + } + } + + setHeader(showTip, warnString, balanceTitleString, balanceContentString, new SpannedString(balanceTipString)); + } + + private void showOrderAndRecord(boolean showOrder) { + String[] titles; + if (showOrder) { + titles = new String[]{MyDetailPagerAdapter.TITLE_ORDER}; + } else { + titles = new String[]{MyDetailPagerAdapter.TITLE_EMPTY}; + } + + MyDetailPagerAdapter adpter = new MyDetailPagerAdapter(this, getSupportFragmentManager(), titles); + viewPager.setAdapter(adpter); + + if (titles.length >= 2) { + WechatTab tabs = (WechatTab) getLayoutInflater().inflate(R.layout.common_pager_tabs, containerHeader, false); + containerHeader.addView(tabs); + tabs.setViewPager(viewPager); + ViewCompat.setElevation(tabs, 0); + + } else if (titles.length == 1) { + if (titles[0].equals(MyDetailPagerAdapter.TITLE_ORDER)) { + View tabs = getLayoutInflater().inflate(R.layout.order_section, containerHeader, false); + containerHeader.addView(tabs); + } + } + + ViewCompat.setElevation(findViewById(R.id.appbarLayout), 0); + + if (showOrder) { + loadOrderData(); + } + + } + + private void setHeader(boolean show, Spanned... spanneds) { + topTip.setVisibility(show ? View.VISIBLE : View.GONE); + TextView[] views = new TextView[]{ + topWarn, balanceTitle, balanceContent, balanceTip + }; + for (int i = 0; i < views.length; ++i) { + if (spanneds[i].length() == 0) { + views[i].setVisibility(View.GONE); + } else { + views[i].setVisibility(View.VISIBLE); + views[i].setText(spanneds[i]); + } + } + } + + @Click + void closeTipButton() { + topTip.setVisibility(View.GONE); + } + + private void loadOrderData() { + String url = String.format("%s/enterprise/%s/orders", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + getNetwork(url, TAG_ORDERS); + } + + private void loadBillings() { + String url = String.format("%s/enterprise/%s/billings", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + getNetwork(url, TAG_BILLINGS); + } + + public ArrayList getOrderList() { + return orderList; + } + + public ArrayList getBillingList() { + return billingList; + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_ORDERS)) { + if (code == 0) { + orderList.clear(); + JSONArray json = respanse.optJSONArray("data"); + for (int i = 0; i < json.length(); ++i) { + orderList.add(new Order(json.optJSONObject(i))); + } + + EventBus.getDefault().post(new EventRefresh(true)); + } else { + + } + } else if (tag.equals(TAG_BILLINGS)) { + if (code == 0) { + billingList.clear(); + JSONArray json = respanse.optJSONArray("data"); + for (int i = 0; i < json.length(); ++i) { + billingList.add(new Billing(json.optJSONObject(i))); + } + EventBus.getDefault().post(new EventRefresh(true)); + } else { + + } + + } else if (tag.equals(TAG_INFO)) { + swipeRefreshLayout.setRefreshing(false); + if (code == 0) { + account = new EnterpriseAccount(respanse.optJSONObject("data")); + initHeader(); + } else { + showButtomToast("刷新失败"); + } + } + } + + private static class MyDetailPagerAdapter extends FragmentPagerAdapter { + + private static final String TITLE_ORDER = "充值订单"; + private static final String TITLE_BILLING = "账单流水"; + private static final String TITLE_EMPTY = "TITLE_EMPTY"; + String[] titles; + + Context context; + + public MyDetailPagerAdapter(Context context, FragmentManager fm, String[] titles) { + super(fm); + this.context = context; + this.titles = titles; + } + + @Override + public Fragment getItem(int position) { + if (position == 0) { + if (titles[position].equals(TITLE_EMPTY)) { + return EmptyFragment_.builder().build(); + } else { + return OrderListFragment_.builder().build(); + } + } else { + return BillingListFragment_.builder().build(); + } + } + + @Override + public int getCount() { + return titles.length; + } + + @Override + public CharSequence getPageTitle(int position) { + return titles[position]; + } + } +} + diff --git a/app/src/enterprise/java/net/coding/program/user/BaseEnterpriseUserListActivity.java b/app/src/enterprise/java/net/coding/program/user/BaseEnterpriseUserListActivity.java new file mode 100644 index 000000000..ca46131ac --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/BaseEnterpriseUserListActivity.java @@ -0,0 +1,110 @@ +package net.coding.program.user; + +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; +import android.text.TextUtils; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.model.EnterpriseUserObject; +import net.coding.program.common.model.UserObject; +import net.coding.program.common.ui.BackActivity; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by chenchao on 2017/1/7. + */ +@EActivity(R.layout.activity_enterprise_add_member) +public abstract class BaseEnterpriseUserListActivity extends BackActivity { + + private static final String TAG_HOST_MEMBERS = "TAG_HOST_MEMBERS"; + + protected ArrayList listData = new ArrayList<>(); + protected ArrayList allListData = new ArrayList<>(); + + @AfterViews + void initBaseEnterpriseUserListActivity() { + String host = String.format("%s/team/%s/members", Global.HOST_API, EnterpriseInfo.instance().getGlobalkey()); + getNetwork(host, TAG_HOST_MEMBERS); + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_HOST_MEMBERS)) { + if (code == 0) { + parseUserJson(respanse); + } else { + showErrorMsg(code, respanse); + } + } else { + super.parseJson(code, respanse, tag, pos, data); + } + } + + protected void parseUserJson(JSONObject respanse) { + listData.clear(); + allListData.clear(); + JSONArray jsonArray = respanse.optJSONArray("data"); + for (int i = 0; i < jsonArray.length(); ++i) { + EnterpriseUserObject user = new EnterpriseUserObject(jsonArray.optJSONObject(i)); + allListData.add(user.user); + } + + Collections.sort(allListData); + listData.addAll(allListData); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.users_fans, menu); + + MenuItem searchItem = menu.findItem(R.id.action_search); + searchItem.setIcon(R.drawable.ic_menu_search); + SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + searchItem(s); + return true; + } + }); + + return true; + } + + protected void searchItem(String s) { + s = s.toLowerCase(); + + listData.clear(); + + if (TextUtils.isEmpty(s)) { + listData.addAll(allListData); + } else { + for (UserObject item : allListData) { + if (item.global_key.toLowerCase().contains(s) || + item.name.toLowerCase().contains(s)) { + listData.add(item); + } + } + } + } + +} diff --git a/app/src/enterprise/java/net/coding/program/user/EnterpriseAddMemberActivity.java b/app/src/enterprise/java/net/coding/program/user/EnterpriseAddMemberActivity.java new file mode 100644 index 000000000..ff77ba5d2 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/EnterpriseAddMemberActivity.java @@ -0,0 +1,189 @@ +package net.coding.program.user; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import com.loopj.android.http.RequestParams; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.model.ProjectObject; +import net.coding.program.common.model.UserObject; +import net.coding.program.common.umeng.UmengEvent; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.ViewById; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Collections; + +@EActivity(R.layout.activity_enterprise_add_member) +public class EnterpriseAddMemberActivity extends BaseEnterpriseUserListActivity { + + private static final String TAG_HOST_ADD_USER = "TAG_HOST_ADD_USER"; + private static final String TAG_HOST_DELETE_USER = "TAG_HOST_DELETE_USER"; + + ArrayList pickedData = new ArrayList<>(); + + @Extra + ProjectObject projectObject; + + @Extra + ArrayList pickedGlobalKeys; + + @ViewById + protected ListView listView; + + @AfterViews + void initEnterpriseAddMemberActivity() { + listView.setAdapter(adapter); + } + + @Override + protected void parseUserJson(JSONObject respanse) { + super.parseUserJson(respanse); + + for (String item : pickedGlobalKeys) { + for (UserObject user : listData) { + if (item.equals(user.global_key)) { + pickedData.add(user); + break; + } + } + } + + Collections.sort(allListData, (o1, o2) -> { + if (pickedData.contains(o1)) { + if (pickedData.contains(o2)) { + return o1.compareTo(o2); + } else { + return -1; + } + } else if (pickedData.contains(o2)) { + return 1; + } else { + return o1.compareTo(o2); + } + }); + + listData.clear(); + listData.addAll(allListData); + + adapter.notifyDataSetChanged(); + } + + @Override + protected void searchItem(String s) { + super.searchItem(s); + adapter.notifyDataSetChanged(); + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_HOST_ADD_USER)) { + if (code == 0) { + umengEvent(UmengEvent.PROJECT, "添加成员"); + + pickedData.add((UserObject) data); + + showMiddleToast(String.format("添加项目成员 %s 成功", ((UserObject) data).name)); + } else { + showErrorMsg(code, respanse); + } + adapter.notifyDataSetChanged(); + + } else if (tag.equals(TAG_HOST_DELETE_USER)) { + if (code == 0) { + pickedData.remove((UserObject) data); + + showMiddleToast(String.format("移除项目成员 %s 成功", ((UserObject) data).name)); + } else { + showErrorMsg(code, respanse); + } + adapter.notifyDataSetChanged(); + + } else { + super.parseJson(code, respanse, tag, pos, data); + } + } + + private View.OnClickListener clickMutual = v -> { + UserObject user = (UserObject) v.getTag(R.id.followed); + if (((CheckBox) v).isChecked()) { + final String urlAddUser = Global.HOST_API + "/project/" + projectObject.id + "/members/gk/add"; + RequestParams param = new RequestParams(); + param.put("users", user.global_key); + postNetwork(urlAddUser, param, TAG_HOST_ADD_USER, -1, user); + } else { + final String urlDeleteUser = Global.HOST_API + "/project/%s/kickout/%s"; + String url = String.format(urlDeleteUser, projectObject.getId(), user.id); + postNetwork(url, new RequestParams(), TAG_HOST_DELETE_USER, -1, user); + } + }; + + BaseAdapter adapter = new BaseAdapter() { + @Override + public int getCount() { + return listData.size(); + } + + @Override + public Object getItem(int position) { + return listData.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (convertView == null) { + convertView = mInflater.inflate(R.layout.enterprise_add_member_list_item, parent, false); + holder = new ViewHolder(); + holder.icon = (ImageView) convertView.findViewById(R.id.icon); + holder.name = (TextView) convertView.findViewById(R.id.name); + holder.mutual = (CheckBox) convertView.findViewById(R.id.followed); + holder.bottomDivideLine = convertView.findViewById(R.id.bottomDivideLine); + holder.mutual.setVisibility(View.VISIBLE); + holder.mutual.setOnClickListener(clickMutual); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + final UserObject data = (UserObject) getItem(position); + iconfromNetwork(holder.icon, data.avatar); + holder.name.setText(data.name); + + boolean isPicked = pickedData.contains(data); + int drawableId = isPicked ? R.drawable.checkbox_follow_follow : R.drawable.checkbox_follow_fans; + holder.mutual.setButtonDrawable(drawableId); + holder.mutual.setChecked(isPicked); + holder.mutual.setTag(R.id.followed, data); + + holder.bottomDivideLine.setVisibility(position == (getCount() - 1) ? View.GONE : View.VISIBLE); + + return convertView; + } + }; + + static class ViewHolder { + ImageView icon; + TextView name; + CheckBox mutual; + View bottomDivideLine; + } +} diff --git a/app/src/enterprise/java/net/coding/program/user/EnterpriseLoginActivity.java b/app/src/enterprise/java/net/coding/program/user/EnterpriseLoginActivity.java new file mode 100644 index 000000000..d68152719 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/EnterpriseLoginActivity.java @@ -0,0 +1,620 @@ +package net.coding.program.user; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.loopj.android.http.AsyncHttpClient; +import com.loopj.android.http.AsyncHttpResponseHandler; +import com.loopj.android.http.RequestParams; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.assist.ImageScaleType; +import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; +import com.tencent.android.tpush.XGPushManager; + +import net.coding.program.EnterpriseApp; +import net.coding.program.EnterpriseMainActivity_; +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.GlobalCommon; +import net.coding.program.common.GlobalData; +import net.coding.program.common.SimpleSHA1; +import net.coding.program.common.event.EventLoginSuccess; +import net.coding.program.common.model.AccountInfo; +import net.coding.program.common.model.EnterpriseDetail; +import net.coding.program.common.model.EnterpriseInfo; +import net.coding.program.common.model.UserObject; +import net.coding.program.common.network.MyAsyncHttpClient; +import net.coding.program.common.network.NetworkImpl; +import net.coding.program.common.ui.BaseActivity; +import net.coding.program.common.umeng.UmengEvent; +import net.coding.program.common.util.InputCheck; +import net.coding.program.common.widget.LoginEditTextNew; +import net.coding.program.common.widget.input.SimpleTextWatcher; +import net.coding.program.compatible.CodingCompat; +import net.coding.program.login.PhoneRegisterActivity_; +import net.coding.program.login.auth.AuthInfo; +import net.coding.program.login.auth.TotpClock; +import net.coding.program.login.phone.Close2FAActivity_; +import net.coding.program.login.phone.EnterpriseEmailSetPasswordActivity_; +import net.coding.program.login.phone.EnterprisePrivateEmailSetPasswordActivity_; +import net.coding.program.network.constant.MemberAuthority; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.OnActivityResult; +import org.androidannotations.annotations.ViewById; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Calendar; + +import cz.msebera.android.httpclient.Header; + +@EActivity(R.layout.enterprise_activity_login) +public class EnterpriseLoginActivity extends BaseActivity { + + private final String TAG_HOST_USER = "TAG_HOST_USER"; + private final String TAG_HOST_ENTERPRISE_DETAIL = "TAG_HOST_ENTERPRISE_DETAIL"; + private final String TAG_HOST_IS_ADMIN = "TAG_HOST_IS_ADMIN"; + private final String TAG_HOST_USER_NEED_2FA = "TAG_HOST_USER_NEED_2FA"; + + private static final int RESULT_CLOSE_2FA = 1; + + private final String CLOSE_2FA_TIP = "关闭两步验证"; + private String TAG_HOST_NEED_CAPTCHA = "TAG_HOST_NEED_CAPTCHA"; + private final String TAG_LOGIN = "TAG_LOGIN"; + private final String CE_INFO = "CE_INFO"; + + private static final int RESULT_CLOSE = 100; + + private String ssoType = "default"; + private boolean ssoEnabled = false; + + @Extra + Uri background; + + @Extra + boolean isPrivate = false; + + @ViewById + ImageView backButton; + + @ViewById + TextView login2faMenu, toolbarTitle; + + @ViewById + LoginEditTextNew enterpriseEdit, privateHost; + + @ViewById + ImageView imageValifyMain; + + @ViewById + LoginEditTextNew editName, editPassword, editValifyMain, edit2FA; + + @ViewById + View enterpriseLine, valifyLineMain, privateHostLayout, hostLayout, normalHostLayout; + + @ViewById + View captchaLayout, loginButton, layout2fa, loginLayout, layoutRoot; + + @ViewById + TextView loginFail; + + // 快速点击 5 次弹出对话框进入 staging 环境 + private int clickIconCount = 0; + private long lastClickTime = 0; + + private String enterpriseGK = ""; + + + DisplayImageOptions options = new DisplayImageOptions.Builder() + .showImageForEmptyUri(R.drawable.icon_user_monkey) + .showImageOnFail(R.drawable.icon_user_monkey) + .resetViewBeforeLoading(true) + .cacheOnDisk(true) + .imageScaleType(ImageScaleType.EXACTLY) + .bitmapConfig(Bitmap.Config.RGB_565) + .considerExifParams(true) + .displayer(new FadeInBitmapDisplayer(300)) + .build(); + + View androidContent; + + TextWatcher textWatcher = new SimpleTextWatcher() { + @Override + public void afterTextChanged(Editable s) { + upateLoginButton(); + } + }; + + private String globalKey = ""; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + XGPushManager.registerPush(this); + + if (AccountInfo.isLogin(this)) { + String gk = GlobalData.getEnterpriseGK(); + if (gk.equalsIgnoreCase(EnterpriseApp.PRIVATE_GK)) { + isPrivate = true; + } + } + } + + @AfterViews + void initEnterpriseLoginActivity() { + editName.addTextChangedListener(textWatcher); + editPassword.addTextChangedListener(textWatcher); + editValifyMain.addTextChangedListener(textWatcher); + upateLoginButton(); + + androidContent = findViewById(android.R.id.content); + + String lastLoginName = AccountInfo.loadLastLoginName(this); + if (!lastLoginName.isEmpty()) { + editName.setText(lastLoginName); + editPassword.requestFocus(); + } + + String lastCompanyName = AccountInfo.loadLastCompanyName(this); + if (!lastCompanyName.isEmpty()) { + enterpriseEdit.setText(lastCompanyName); + } + + if (isPrivate) { + String lastHost = AccountInfo.loadLastPrivateHost(this); + privateHost.setText(lastHost); + } + + enterpriseEdit.setOnEditFocusChange(createEditLineFocus(enterpriseLine)); + editValifyMain.setOnFocusChangeListener(createEditLineFocus(valifyLineMain)); + + hostLayout.setVisibility(View.VISIBLE); + if (isPrivate) { + normalHostLayout.setVisibility(View.GONE); + privateHostLayout.setVisibility(View.VISIBLE); + } else { + normalHostLayout.setVisibility(View.VISIBLE); + privateHostLayout.setVisibility(View.GONE); + } + } + + @Click + void clickNext() { + hostLayout.setVisibility(View.GONE); + enterpriseGK = enterpriseEdit.getTextString(); + toolbarTitle.setText(String.format("登录到\n%s", enterpriseGK)); + } + + @Click + void clickPrivateNext() { + hostLayout.setVisibility(View.GONE); + enterpriseGK = EnterpriseApp.PRIVATE_GK; + + String input = privateHost.getTextString(); + String divide = "://"; + int pos = input.indexOf(divide); + if (pos != -1) { + input = input.substring(pos + divide.length()); + } + + toolbarTitle.setText(String.format("登录到\n%s", input)); + } + + @Click + void backButton() { + onBackPressed(); + } + + @Click + void toolbarTitle() { + long clickTime = Calendar.getInstance().getTimeInMillis(); + long lastTemp = lastClickTime; + lastClickTime = clickTime; + if (clickTime - lastTemp < 1000) { + ++clickIconCount; + } else { + clickIconCount = 1; + } + + if (clickIconCount >= 5) { + clickIconCount = 0; + + AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle); + View content = getLayoutInflater().inflate(R.layout.host_setting, null); + final EditText editText = content.findViewById(R.id.edit); + AccountInfo.CustomHost customHost = AccountInfo.getCustomHost(this); + editText.setText(customHost.getHost()); + editText.setHint(Global.DEFAULT_HOST); + builder.setView(content) + .setPositiveButton(R.string.action_ok, (dialog, which) -> { + String hostString = editText.getText().toString(); + AccountInfo.CustomHost customHost1 = new AccountInfo.CustomHost(hostString, ""); + if (!hostString.isEmpty()) { + AccountInfo.saveCustomHost(this, customHost1); + } else { + AccountInfo.removeCustomHost(this); + } + + AccountInfo.loginOut(this); + setResult(RESULT_OK); + }) + .setNegativeButton(R.string.action_cancel, null) + .show(); + } + } + + @Click + void imageValifyMain() { + editValifyMain.getEditText().requestFocus(); + downloadValifyPhoto(); + } + + @Click + void register() { + Global.popSoftkeyboard(this, editName, false); + PhoneRegisterActivity_.intent(this) + .startForResult(RESULT_CLOSE); + } + + @OnActivityResult(RESULT_CLOSE) + void resultRegiter(int result) { + if (result == Activity.RESULT_OK) { + EventLoginSuccess.Companion.sendMessage(); + finish(); + } + } + + private void needCaptcha() { + getNetwork(Global.HOST_API + "/captcha/login", TAG_HOST_NEED_CAPTCHA); + } + + private void downloadValifyPhoto() { + String host = Global.HOST_API + "/getCaptcha"; + AsyncHttpClient client = MyAsyncHttpClient.createClient(this); + + client.get(host, new AsyncHttpResponseHandler() { + @Override + public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { + imageValifyMain.setImageBitmap(BitmapFactory.decodeByteArray(responseBody, 0, responseBody.length)); + editValifyMain.setText(""); + } + + @Override + public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { + showMiddleToast("获取验证码失败"); + } + }); + } + + @Click + protected final void loginButton() { + updateGlobalHost(); + getNetwork(Global.HOST_API + "/enterprise/info/ce", CE_INFO); + } + + private void login2fa() { + String input = edit2FA.getText().toString(); + if (input.isEmpty()) { + showMiddleToast("请输入身份验证器中的验证码"); + return; + } + + RequestParams params = new RequestParams(); + params.put("code", input); + postNetwork(Global.HOST_API + "/check_two_factor_auth_code", params, TAG_HOST_USER_NEED_2FA); + showProgressBar(true, "登录中"); + + Global.popSoftkeyboard(this, edit2FA, false); + } + + private void login(boolean sha1) { + try { + String name = editName.getTextString(); + String password = editPassword.getTextString(); + String captcha = editValifyMain.getTextString(); + + if (name.isEmpty()) { + showMiddleToast("邮箱或用户名不能为空"); + return; + } + + if (password.isEmpty()) { + showMiddleToast("密码不能为空"); + return; + } + + RequestParams params = new RequestParams(); + + params.put("account", name); + if (sha1) { + params.put("password", SimpleSHA1.sha1(password)); + } else { + params.put("password", password); + } + if (captchaLayout.getVisibility() == View.VISIBLE) { + params.put("j_captcha", captcha); + } + params.put("remember_me", true); + + updateGlobalHost(); + String HOST_LOGIN = String.format("%s/v2/account/login", Global.HOST_API); + + postNetwork(HOST_LOGIN, params, TAG_LOGIN); + showProgressBar(true, R.string.logining); + + Global.popSoftkeyboard(this, editName, false); + + } catch (Exception e) { + Global.errorLog(e); + } + } + + private void login() { + login(true); + } + + private void updateGlobalHost() { + if (isPrivate) { + EnterpriseApp.setPrivateHost(privateHost.getTextString()); + } else { + EnterpriseApp.setHost(enterpriseEdit.getTextString()); + } + } + + @Click + protected final void loginFail() { + String account = editName.getText().toString(); + if (!InputCheck.isPhone(account) && !InputCheck.isEmail(account)) { + account = ""; + } + + if (isPrivate) { + EnterprisePrivateEmailSetPasswordActivity_.intent(this) + .enterpriseName(privateHost.getTextString()) + .start(); + } else { + EnterpriseEmailSetPasswordActivity_.intent(this) + .enterpriseName(enterpriseGK) + .account(account) + .start(); + } + } + + @Click + void login2faMenu() { + if (login2faMenu.getText().equals(CLOSE_2FA_TIP)) { + Close2FAActivity_.intent(this).startForResult(RESULT_CLOSE_2FA); + } else { + GlobalCommon.start2FAActivity(this); + } + } + + @OnActivityResult(RESULT_CLOSE_2FA) + void onResultClose2FA(int resultCode) { + if (resultCode == RESULT_OK) { + show2FA(false); + } + } + + private void show2FA(boolean show) { + if (show) { + layout2fa.setVisibility(View.VISIBLE); + loginLayout.setVisibility(View.GONE); + String uri = AccountInfo.loadAuth(this, globalKey); + if (!uri.isEmpty()) { + String code2FA = new AuthInfo(uri, new TotpClock(this)).getCode(); + edit2FA.getText().clear(); + edit2FA.getText().insert(0, code2FA); + loginButton(); + } + + loginFail.setVisibility(View.GONE); + + login2faMenu.setText(CLOSE_2FA_TIP); + + + } else { + layout2fa.setVisibility(View.GONE); + loginLayout.setVisibility(View.VISIBLE); + + loginFail.setVisibility(View.VISIBLE); + + login2faMenu.setText("两步验证"); + } + } + + private UserObject currentUserInfo = null; + private EnterpriseDetail enterpriseDetail = null; + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_LOGIN)) { + if (code == 0) { + updateGlobalHost(); + EnterpriseMainActivity_.setNeedWarnEmailNoValidLogin(); + loginSuccess(respanse); + umengEvent(UmengEvent.USER, "普通登录"); + if (isPrivate) { + AccountInfo.saveLastPrivateHost(this, Global.HOST); + } + } else if (code == 3205) { + updateGlobalHost(); + EnterpriseMainActivity_.setNeedWarnEmailNoValidLogin(); + umengEvent(UmengEvent.USER, "2fa登录"); + globalKey = respanse.optJSONObject("msg").optString("two_factor_auth_code_not_empty", ""); + show2FA(true); + showProgressBar(false); + + } else { + loginFail(code, respanse, true); + } + + } else if (tag.equals(CE_INFO)) { + if (code == 0) { + try { + ssoEnabled = respanse.getJSONObject("data").getJSONObject("settings").getBoolean("ssoEnabled"); + ssoType = respanse.getJSONObject("data").getJSONObject("settings").getString("ssoType"); + } catch (Exception e) { + ssoEnabled = false; + ssoType = "default"; + } + if (layout2fa.getVisibility() == View.GONE) { + if (ssoEnabled && "ldap".equals(ssoType)) { + login(false); + } else { + login(); + } + } else { + login2fa(); + } + } + } else if (tag.equals(TAG_HOST_USER_NEED_2FA)) { + if (code == 0) { + loginSuccess(respanse); + if (isPrivate) { + AccountInfo.saveLastPrivateHost(this, Global.HOST); + } + } else { + loginFail(code, respanse, false); + } + } else if (tag.equals(TAG_HOST_USER)) { + if (code == 0) { + currentUserInfo = new UserObject(respanse.getJSONObject("data")); + + if (isPrivate) { + String url = String.format("%s/team/%s/get", Global.HOST_API, EnterpriseApp.PRIVATE_GK); + getNetwork(url, TAG_HOST_ENTERPRISE_DETAIL); + } else { + String url = String.format("%s/team/%s/get", Global.HOST_API, enterpriseGK); + getNetwork(url, TAG_HOST_ENTERPRISE_DETAIL); + } + } else { + showProgressBar(false); + showErrorMsg(code, respanse); + } + } else if (tag.equals(TAG_HOST_ENTERPRISE_DETAIL)) { + if (code == 0) { + enterpriseDetail = new EnterpriseDetail(respanse.optJSONObject("data")); + + String url = String.format("%s/team/%s/is_admin", Global.HOST_API, enterpriseGK); + getNetwork(url, TAG_HOST_IS_ADMIN); + } else { + showProgressBar(false); + showErrorMsg(code, respanse); + } + + } else if (tag.equals(TAG_HOST_IS_ADMIN)) { // 判断是否管理员 + if (code == 0) { + showProgressBar(false); + boolean isAdmin = respanse.optBoolean("data", false); + if (isAdmin) { + if (!EnterpriseInfo.instance().canManagerEnterprise()) { + enterpriseDetail.setIdentity(MemberAuthority.manager); + } + } + jumpMainActivity(); + } else { + showProgressBar(false); + showErrorMsg(code, respanse); + } + + } else if (tag.equals(TAG_HOST_NEED_CAPTCHA)) { + if (code == 0) { + if (respanse.getBoolean("data")) { + captchaLayout.setVisibility(View.VISIBLE); + downloadValifyPhoto(); + } + } else { + showErrorMsg(code, respanse); + } + } + } + + private void jumpMainActivity() throws JSONException { + EnterpriseInfo.instance().update(this, enterpriseDetail); + + AccountInfo.saveAccount(this, currentUserInfo); + GlobalData.sUserObject = currentUserInfo; + AccountInfo.saveReloginInfo(this, currentUserInfo); + + Global.syncCookie(this); + + String name = editName.getText().toString(); + AccountInfo.saveLastLoginName(this, name); + + String companyName = enterpriseGK; + AccountInfo.saveLastCompanyName(this, companyName); + + EventLoginSuccess.Companion.sendMessage(); + startActivity(new Intent(this, CodingCompat.instance().getMainActivity())); + finish(); + overridePendingTransition(R.anim.entrance_fade_in, R.anim.entrance_fade_out); + } + + private void loginFail(int code, JSONObject respanse, boolean needCaptcha) { + String msg = Global.getErrorMsg(respanse).replaceAll(" (.*?) ", "\n$1"); + showMiddleToast(msg); + showProgressBar(false); + if (code != NetworkImpl.NETWORK_ERROR && + code != NetworkImpl.NETWORK_ERROR_SERVICE && + needCaptcha) { + needCaptcha(); + } + } + + private void loginSuccess(JSONObject respanse) throws JSONException { + UserObject user = new UserObject(respanse.getJSONObject("data")); + + String HOST_USER = Global.HOST_API + "/user/key/%s"; + getNetwork(String.format(HOST_USER, user.global_key), TAG_HOST_USER); + showProgressBar(true, R.string.logining); + } + + @Override + public void onBackPressed() { + if (layout2fa.getVisibility() == View.GONE) { + if (hostLayout.getVisibility() != View.VISIBLE) { + hostLayout.setVisibility(View.VISIBLE); + } else { + finish(); + } + } else { + show2FA(false); + } + } + + private void upateLoginButton() { + if (editName.getText().length() == 0) { + loginButton.setEnabled(false); + return; + } + + if (editPassword.getText().length() == 0) { + loginButton.setEnabled(false); + return; + } + + if (captchaLayout.getVisibility() == View.VISIBLE && + editValifyMain.getText().length() == 0) { + loginButton.setEnabled(false); + return; + } + + loginButton.setEnabled(true); + } +} \ No newline at end of file diff --git a/app/src/enterprise/java/net/coding/program/user/EnterpriseMyDetailActivity.java b/app/src/enterprise/java/net/coding/program/user/EnterpriseMyDetailActivity.java new file mode 100644 index 000000000..045738702 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/EnterpriseMyDetailActivity.java @@ -0,0 +1,60 @@ +package net.coding.program.user; + +import net.coding.program.R; +import net.coding.program.UserDetailEditActivity_; +import net.coding.program.common.Global; +import net.coding.program.common.GlobalCommon; +import net.coding.program.common.GlobalData; +import net.coding.program.common.model.UserObject; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.json.JSONException; +import org.json.JSONObject; + +// TODO: 2018/1/4 删除 +@EActivity(R.layout.enterprise_activity_my_detail) +public class EnterpriseMyDetailActivity extends UserDetailCommonActivity { + + public final int RESULT_EDIT = 0; + private final String TAG_HOST_USER_INFO = "TAG_HOST_USER_INFO"; + + @AfterViews + void initMyDetailActivity() { + bindUI(GlobalData.sUserObject); + tv_follow_state.setText("编辑资料"); + rl_follow_state.setOnClickListener(v -> { + UserDetailEditActivity_ + .intent(this) + .startForResult(RESULT_EDIT); + }); + + final String HOST_USER_INFO = Global.HOST_API + "/user/key/"; + getNetwork(HOST_USER_INFO + GlobalData.sUserObject.global_key, TAG_HOST_USER_INFO); + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_HOST_USER_INFO)) { + if (code == 0) { + mUserObject = new UserObject(respanse.getJSONObject("data")); + bindUI(mUserObject); + } else { + showButtomToast("获取用户信息错误"); + } + } + openActivenessResult(code, respanse, tag); + } + + @Override + protected void onStart() { + super.onStart(); + + bindUI(GlobalData.sUserObject); + } + + public int getActionBarSize() { + return GlobalCommon.dpToPx(48); + } + +} diff --git a/app/src/enterprise/java/net/coding/program/user/EnterpriseUserDetailActivity.java b/app/src/enterprise/java/net/coding/program/user/EnterpriseUserDetailActivity.java new file mode 100644 index 000000000..389975253 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/EnterpriseUserDetailActivity.java @@ -0,0 +1,86 @@ +package net.coding.program.user; + +import android.view.View; +import android.widget.TextView; + +import net.coding.program.R; +import net.coding.program.common.Global; +import net.coding.program.common.GlobalCommon; +import net.coding.program.common.GlobalData; +import net.coding.program.common.model.UserObject; +import net.coding.program.message.MessageListActivity_; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Click; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.androidannotations.annotations.ViewById; +import org.json.JSONException; +import org.json.JSONObject; + +// TODO: 2018/1/4 删除 +@EActivity(R.layout.enterprise_activity_my_detail) +public class EnterpriseUserDetailActivity extends UserDetailCommonActivity { + + private final String TAG_HOST_USER_INFO = "TAG_HOST_USER_INFO"; + private final String HOST_USER_INFO = Global.HOST_API + "/user/key/"; + + @Extra + String globalKey; + + @ViewById + TextView moreDetail; + + @AfterViews + void initEnterpriseUserDetailActivity() { + if (GlobalData.sUserObject.global_key.equals(globalKey)) { + EnterpriseMyDetailActivity_.intent(this).start(); + finish(); + return; + } + + getNetwork(HOST_USER_INFO + globalKey, TAG_HOST_USER_INFO); + + } + + @Click + void moreDetail() { + if (mUserObject == null) { + return; + } + + UserDetailMoreActivity_.intent(this) + .mUserObject(mUserObject) + .start(); + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_HOST_USER_INFO)) { + if (code == 0) { + moreDetail.setVisibility(View.VISIBLE); + mUserObject = new UserObject(respanse.getJSONObject("data")); + bindUI(mUserObject); + } else { + showButtomToast("获取用户信息错误"); + } + } + openActivenessResult(code, respanse, tag); + } + + @Override + protected void bindUI(UserObject mUserObject) { + super.bindUI(mUserObject); + tv_follow_state.setText("发送私信"); + tv_follow_state.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_private_letter, 0, 0, 0); + rl_follow_state.setOnClickListener(v -> { + MessageListActivity_.intent(v.getContext()).mGlobalKey(globalKey).start(); + }); + } + + public int getActionBarSize() { + return GlobalCommon.dpToPx(48); + } + + +} diff --git a/app/src/enterprise/java/net/coding/program/user/PickUserActivity.java b/app/src/enterprise/java/net/coding/program/user/PickUserActivity.java new file mode 100644 index 000000000..55e731f84 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/PickUserActivity.java @@ -0,0 +1,226 @@ +package net.coding.program.user; + +import android.app.Activity; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.SectionIndexer; +import android.widget.TextView; + +import net.coding.program.R; +import net.coding.program.common.model.UserObject; +import net.coding.program.third.sidebar.IndexableListView; +import net.coding.program.third.sidebar.StringMatcher; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.ViewById; +import org.json.JSONObject; + +import java.util.ArrayList; + +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; + +@EActivity(R.layout.activity_pick_user) +public class PickUserActivity extends BaseEnterpriseUserListActivity { + + @ViewById + IndexableListView listView; + + UserAdapter adapter = new UserAdapter(); + + @AfterViews + void initPickUserActivity() { + adapter.initSection(); + listView.setAdapter(adapter); + listView.setFastScrollEnabled(true); + listView.setFastScrollAlwaysVisible(true); + + initListItemClick(); + } + + protected void initListItemClick() { + listView.setOnItemClickListener((parent, view, position, id) -> { + Intent intent = new Intent(); + UserObject user = (UserObject) parent.getItemAtPosition(position); + intent.putExtra(UsersListActivity.RESULT_EXTRA_NAME, user.name); + intent.putExtra(UsersListActivity.RESULT_EXTRA_USESR, user); + setResult(Activity.RESULT_OK, intent); + finish(); + }); + } + + @Override + protected void searchItem(String s) { + super.searchItem(s); + + adapter.notifyDataSetChanged(); + } + + @Override + protected void parseUserJson(JSONObject respanse) { + super.parseUserJson(respanse); + adapter.notifyDataSetChanged(); + } + + class UserAdapter extends BaseAdapter implements SectionIndexer, StickyListHeadersAdapter { + + private String mSections = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"; + private ArrayListmSectionTitle = new ArrayList<>(); + private ArrayList mSectionId = new ArrayList<>(); + + public void initSection() { + mSectionTitle.clear(); + mSectionId.clear(); + + if (allListData.size() > 0) { + String lastLetter = ""; + + for (int i = 0; i < allListData.size(); ++i) { + UserObject item = allListData.get(i); + if (!item.getFirstLetter().equals(lastLetter)) { + lastLetter = item.getFirstLetter(); + mSectionTitle.add(item.getFirstLetter()); + mSectionId.add(i); + } + } + } + } + + @Override + public int getCount() { + return listData.size(); + } + + @Override + public Object getItem(int position) { + return listData.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + final ViewHolder holder; + if (convertView == null) { + convertView = mInflater.inflate(R.layout.activity_users_list_item, parent, false); + holder = new ViewHolder(); + holder.name = (TextView) convertView.findViewById(R.id.name); + holder.icon = (ImageView) convertView.findViewById(R.id.icon); + holder.divideTitle = (TextView) convertView.findViewById(R.id.divideTitle); + holder.divideLine = convertView.findViewById(R.id.divide_line); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + final UserObject data = listData.get(position); + + if (isSection(position)) { + holder.divideTitle.setVisibility(View.VISIBLE); + holder.divideTitle.setText(data.getFirstLetter()); + holder.divideLine.setVisibility(View.GONE); + } else { + holder.divideTitle.setVisibility(View.GONE); + holder.divideLine.setVisibility(View.VISIBLE); + } + + holder.name.setText(data.name); + iconfromNetwork(holder.icon, data.avatar); + + return convertView; + } + + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + initSection(); + } + + private boolean isSection(int pos) { + if (getCount() == 0) { + return true; + } + + if (pos == 0) { + return true; + } + + String currentItem = allListData.get(pos).getFirstLetter(); + String preItem = allListData.get(pos - 1).getFirstLetter(); + return !currentItem.equals(preItem); + } + + @Override + public int getPositionForSection(int section) { + // If there is no item for current section, previous section will be selected + for (int i = section; i >= 0; i--) { + for (int j = 0; j < getCount(); j++) { + if (i == 0) { + // For numeric section + for (int k = 0; k <= 9; k++) { + if (StringMatcher.match(((UserObject) getItem(j)).getFirstLetter().toUpperCase(), String.valueOf(k))) + return j; + } + } else { + if (StringMatcher.match(((UserObject) getItem(j)).getFirstLetter().toUpperCase(), String.valueOf(mSections.charAt(i)))) + return j; + } + } + } + return 0; + } + + @Override + public int getSectionForPosition(int position) { + return 0; + } + + @Override + public Object[] getSections() { + String[] sections = new String[mSections.length()]; + for (int i = 0; i < mSections.length(); i++) + sections[i] = String.valueOf(mSections.charAt(i)); + return sections; + } + + @Override + public View getHeaderView(int position, View convertView, ViewGroup parent) { + HeaderViewHolder holder; + if (convertView == null) { + holder = new HeaderViewHolder(); + convertView = getLayoutInflater().inflate(R.layout.fragment_project_dynamic_list_head, parent, false); + holder.mHead = (TextView) convertView.findViewById(R.id.head); + convertView.setTag(holder); + } else { + holder = (HeaderViewHolder) convertView.getTag(); + } + + holder.mHead.setText(mSectionTitle.get(getSectionForPosition(position))); + return convertView; + } + + @Override + public long getHeaderId(int i) { + return getSectionForPosition(i); + } + + class HeaderViewHolder { + TextView mHead; + } + + } + + + static class ViewHolder { + ImageView icon; + TextView name; + TextView divideTitle; + View divideLine; + } + +} diff --git a/app/src/enterprise/java/net/coding/program/user/PickUserRelayMessageActivity.java b/app/src/enterprise/java/net/coding/program/user/PickUserRelayMessageActivity.java new file mode 100644 index 000000000..e9be37b09 --- /dev/null +++ b/app/src/enterprise/java/net/coding/program/user/PickUserRelayMessageActivity.java @@ -0,0 +1,62 @@ +package net.coding.program.user; + +import com.loopj.android.http.RequestParams; + +import net.coding.program.R; +import net.coding.program.common.HtmlContent; +import net.coding.program.common.model.UserObject; +import net.coding.program.common.param.MessageParse; +import net.coding.program.message.MessageListActivity; + +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.Extra; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by chenchao on 2017/1/9. + * 选择成员转发私信 + */ +@EActivity(R.layout.activity_pick_user) +public class PickUserRelayMessageActivity extends PickUserActivity { + + private static final String TAG_RELAY_MESSAGE = "TAG_RELAY_MESSAGE"; + @Extra + String relayString = ""; + + @Override + protected void initListItemClick() { + listView.setOnItemClickListener((parent, view, position, id) -> { + UserObject user = (UserObject) parent.getItemAtPosition(position); + showDialog("转发给" + user.name, (dialog, which) -> { + MessageParse messageParse = HtmlContent.parseMessage(relayString); + RequestParams params = new RequestParams(); + String text = messageParse.text; + for (String url : messageParse.uris) { + String photoTemplate = "\n"; + text += String.format(photoTemplate, url); + + } + params.put("content", text); + params.put("receiver_global_key", user.global_key); + postNetwork(MessageListActivity.getSendMessage(), params, TAG_RELAY_MESSAGE); + showProgressBar(true, "发送中..."); + }); + }); + } + + @Override + public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { + if (tag.equals(TAG_RELAY_MESSAGE)) { + showProgressBar(false); + if (code == 0) { + showMiddleToast("发送成功"); + finish(); + } else { + showErrorMsg(code, respanse); + } + } else { + super.parseJson(code, respanse, tag, pos, data); + } + } +} diff --git a/app/src/enterprise/res/anim/fade_in.xml b/app/src/enterprise/res/anim/fade_in.xml new file mode 100644 index 000000000..c9516535a --- /dev/null +++ b/app/src/enterprise/res/anim/fade_in.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/enterprise/res/anim/fade_out.xml b/app/src/enterprise/res/anim/fade_out.xml new file mode 100644 index 000000000..78b284e82 --- /dev/null +++ b/app/src/enterprise/res/anim/fade_out.xml @@ -0,0 +1,11 @@ ++ + + + + + diff --git a/app/src/enterprise/res/drawable-hdpi/app_icon.png b/app/src/enterprise/res/drawable-hdpi/app_icon.png new file mode 100644 index 000000000..5f0a5346a Binary files /dev/null and b/app/src/enterprise/res/drawable-hdpi/app_icon.png differ diff --git a/app/src/enterprise/res/drawable-mdpi/app_icon.png b/app/src/enterprise/res/drawable-mdpi/app_icon.png new file mode 100644 index 000000000..ab772ce03 Binary files /dev/null and b/app/src/enterprise/res/drawable-mdpi/app_icon.png differ diff --git a/app/src/enterprise/res/drawable-xhdpi/app_icon.png b/app/src/enterprise/res/drawable-xhdpi/app_icon.png new file mode 100644 index 000000000..5cb5ce885 Binary files /dev/null and b/app/src/enterprise/res/drawable-xhdpi/app_icon.png differ diff --git a/app/src/enterprise/res/drawable-xxhdpi/app_icon.png b/app/src/enterprise/res/drawable-xxhdpi/app_icon.png new file mode 100644 index 000000000..df7c80b09 Binary files /dev/null and b/app/src/enterprise/res/drawable-xxhdpi/app_icon.png differ diff --git a/app/src/enterprise/res/drawable-xxhdpi/icon_user_monkey_circle.png b/app/src/enterprise/res/drawable-xxhdpi/icon_user_monkey_circle.png new file mode 100644 index 000000000..468d86760 Binary files /dev/null and b/app/src/enterprise/res/drawable-xxhdpi/icon_user_monkey_circle.png differ diff --git a/app/src/enterprise/res/drawable-xxhdpi/push_icon.png b/app/src/enterprise/res/drawable-xxhdpi/push_icon.png new file mode 100644 index 000000000..db8bef4d5 Binary files /dev/null and b/app/src/enterprise/res/drawable-xxhdpi/push_icon.png differ diff --git a/app/src/enterprise/res/drawable/guide0_circle0.xml b/app/src/enterprise/res/drawable/guide0_circle0.xml new file mode 100644 index 000000000..12a1b4c0c --- /dev/null +++ b/app/src/enterprise/res/drawable/guide0_circle0.xml @@ -0,0 +1,5 @@ + ++ + \ No newline at end of file diff --git a/app/src/enterprise/res/drawable/guide0_circle1.xml b/app/src/enterprise/res/drawable/guide0_circle1.xml new file mode 100644 index 000000000..c2b9db004 --- /dev/null +++ b/app/src/enterprise/res/drawable/guide0_circle1.xml @@ -0,0 +1,5 @@ + ++ + \ No newline at end of file diff --git a/app/src/enterprise/res/drawable/guide0_circle2.xml b/app/src/enterprise/res/drawable/guide0_circle2.xml new file mode 100644 index 000000000..b9216a90b --- /dev/null +++ b/app/src/enterprise/res/drawable/guide0_circle2.xml @@ -0,0 +1,5 @@ + ++ + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_about.xml b/app/src/enterprise/res/layout/activity_about.xml new file mode 100755 index 000000000..f43012cf3 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_about.xml @@ -0,0 +1,147 @@ ++ + + + + diff --git a/app/src/enterprise/res/layout/activity_close_2fa.xml b/app/src/enterprise/res/layout/activity_close_2fa.xml new file mode 100644 index 000000000..f93a3c209 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_close_2fa.xml @@ -0,0 +1,121 @@ + ++ + + + + + ++ + + + + + ++ + + + + ++ + + + + + + ++ + + + + + ++ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_enterprise_account.xml b/app/src/enterprise/res/layout/activity_enterprise_account.xml new file mode 100644 index 000000000..cee2ca3fb --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_account.xml @@ -0,0 +1,139 @@ + ++ + ++ + + ++ + + ++ + + ++ + + ++ + + + + + + + + + + ++ + + + + + + + + + diff --git a/app/src/enterprise/res/layout/activity_enterprise_account_toolbar.xml b/app/src/enterprise/res/layout/activity_enterprise_account_toolbar.xml new file mode 100644 index 000000000..8eafb5c3e --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_account_toolbar.xml @@ -0,0 +1,17 @@ + ++ + + ++ + + ++ + + + + + + ++ + + ++ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/enterprise/res/layout/activity_enterprise_add_member.xml b/app/src/enterprise/res/layout/activity_enterprise_add_member.xml new file mode 100644 index 000000000..8e0cfc3b6 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_add_member.xml @@ -0,0 +1,19 @@ + ++ + + + ++ + diff --git a/app/src/enterprise/res/layout/activity_enterprise_entrance.xml b/app/src/enterprise/res/layout/activity_enterprise_entrance.xml new file mode 100755 index 000000000..edf74ab46 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_entrance.xml @@ -0,0 +1,34 @@ + ++ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_enterprise_guide.xml b/app/src/enterprise/res/layout/activity_enterprise_guide.xml new file mode 100644 index 000000000..506828069 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_guide.xml @@ -0,0 +1,178 @@ + ++ + + + + + diff --git a/app/src/enterprise/res/layout/activity_enterprise_main.xml b/app/src/enterprise/res/layout/activity_enterprise_main.xml new file mode 100644 index 000000000..06ee65ec6 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_main.xml @@ -0,0 +1,20 @@ + ++ + + ++ + + + + + + + + ++ + + ++ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_enterprise_setting.xml b/app/src/enterprise/res/layout/activity_enterprise_setting.xml new file mode 100644 index 000000000..500f8e8e9 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_setting.xml @@ -0,0 +1,108 @@ + ++ + + + + + diff --git a/app/src/enterprise/res/layout/activity_enterprise_support.xml b/app/src/enterprise/res/layout/activity_enterprise_support.xml new file mode 100644 index 000000000..7ed6c8e6c --- /dev/null +++ b/app/src/enterprise/res/layout/activity_enterprise_support.xml @@ -0,0 +1,103 @@ + ++ + + + + ++ + + + + + + + + ++ + + + + + + + + ++ + + + + + + + diff --git a/app/src/enterprise/res/layout/activity_help.xml b/app/src/enterprise/res/layout/activity_help.xml new file mode 100644 index 000000000..da2d8e684 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_help.xml @@ -0,0 +1,68 @@ ++ + + + + ++ + + + + + + + + ++ + + + + + + + + ++ + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_manage_member.xml b/app/src/enterprise/res/layout/activity_manage_member.xml new file mode 100644 index 000000000..b88649a3a --- /dev/null +++ b/app/src/enterprise/res/layout/activity_manage_member.xml @@ -0,0 +1,19 @@ + ++ + + ++ + + ++ + + ++ + + + + + + ++ + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/activity_maopao_detail.xml b/app/src/enterprise/res/layout/activity_maopao_detail.xml new file mode 100755 index 000000000..73639a2f5 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_maopao_detail.xml @@ -0,0 +1,38 @@ ++ + + + diff --git a/app/src/enterprise/res/layout/activity_order_main.xml b/app/src/enterprise/res/layout/activity_order_main.xml new file mode 100644 index 000000000..bd99936f1 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_order_main.xml @@ -0,0 +1,111 @@ + ++ + + ++ + ++ + + + + + diff --git a/app/src/enterprise/res/layout/activity_pick_user.xml b/app/src/enterprise/res/layout/activity_pick_user.xml new file mode 100644 index 000000000..af69d69c6 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_pick_user.xml @@ -0,0 +1,20 @@ + ++ + + ++ + + + + + + + + ++ + + ++ + + ++ + + + + + + + + + + + + + + + ++ + + diff --git a/app/src/enterprise/res/layout/activity_set_enterprise_authority.xml b/app/src/enterprise/res/layout/activity_set_enterprise_authority.xml new file mode 100644 index 000000000..92edb30b5 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_set_enterprise_authority.xml @@ -0,0 +1,34 @@ + ++ + + + diff --git a/app/src/enterprise/res/layout/activity_user_detail_more.xml b/app/src/enterprise/res/layout/activity_user_detail_more.xml new file mode 100644 index 000000000..046fda71f --- /dev/null +++ b/app/src/enterprise/res/layout/activity_user_detail_more.xml @@ -0,0 +1,161 @@ ++ + + ++ + + + + + + + + + + + + + diff --git a/app/src/enterprise/res/layout/activity_users_list_item.xml b/app/src/enterprise/res/layout/activity_users_list_item.xml new file mode 100755 index 000000000..8b8c5bb15 --- /dev/null +++ b/app/src/enterprise/res/layout/activity_users_list_item.xml @@ -0,0 +1,60 @@ + ++ + + ++ + + ++ + + + + + ++ + + + + + + + + + + ++ + + + + + + + + + + + + + + + ++ + + + + + + + + + + + + + + + + + + + ++ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/enterprise/res/layout/common_pick_project_list_item.xml b/app/src/enterprise/res/layout/common_pick_project_list_item.xml new file mode 100755 index 000000000..27b83963c --- /dev/null +++ b/app/src/enterprise/res/layout/common_pick_project_list_item.xml @@ -0,0 +1,43 @@ + ++ + + ++ + + + + + + ++ + + + + + diff --git a/app/src/enterprise/res/layout/enterprise_activity_email_set_password.xml b/app/src/enterprise/res/layout/enterprise_activity_email_set_password.xml new file mode 100644 index 000000000..f22493736 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_activity_email_set_password.xml @@ -0,0 +1,110 @@ + ++ + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/enterprise_activity_login.xml b/app/src/enterprise/res/layout/enterprise_activity_login.xml new file mode 100755 index 000000000..e8de045b2 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_activity_login.xml @@ -0,0 +1,303 @@ + ++ + ++ + + ++ + + ++ + + ++ + + + + + + + + + ++ + + + + + + + + + diff --git a/app/src/enterprise/res/layout/enterprise_activity_my_detail.xml b/app/src/enterprise/res/layout/enterprise_activity_my_detail.xml new file mode 100644 index 000000000..42d1b8769 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_activity_my_detail.xml @@ -0,0 +1,23 @@ + ++ + + ++ + + + + + ++ + + + ++ + + + + + + + + ++ + + + + + + + ++ + + ++ + ++ + + ++ + + + ++ + + + ++ + + + + + + + ++ + + + + + + + + ++ + + + + + ++ + + + + + + + ++ + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/enterprise_add_member_list_item.xml b/app/src/enterprise/res/layout/enterprise_add_member_list_item.xml new file mode 100755 index 000000000..58e7e0b21 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_add_member_list_item.xml @@ -0,0 +1,42 @@ + ++ + + ++ + + ++ + + + diff --git a/app/src/enterprise/res/layout/enterprise_fragment_main_setting.xml b/app/src/enterprise/res/layout/enterprise_fragment_main_setting.xml new file mode 100644 index 000000000..1fcaa7136 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_fragment_main_setting.xml @@ -0,0 +1,168 @@ ++ + + + + + + + + + diff --git a/app/src/enterprise/res/layout/enterprise_list_item_project_maopao.xml b/app/src/enterprise/res/layout/enterprise_list_item_project_maopao.xml new file mode 100644 index 000000000..40b30c6a1 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_list_item_project_maopao.xml @@ -0,0 +1,158 @@ + ++ + + ++ + + ++ + + + + + ++ + + ++ + + + + + + + + + + + + ++ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/enterprise_manage_member_list_item.xml b/app/src/enterprise/res/layout/enterprise_manage_member_list_item.xml new file mode 100755 index 000000000..293a97b49 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_manage_member_list_item.xml @@ -0,0 +1,64 @@ + ++ + + + ++ + + + + ++ + + + + + + + + + + ++ + + + + + + + + ++ + + + ++ + + ++ + + + + + + ++ + + + + + + diff --git a/app/src/enterprise/res/layout/enterprise_manage_project_list_item.xml b/app/src/enterprise/res/layout/enterprise_manage_project_list_item.xml new file mode 100755 index 000000000..9b2491c68 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_manage_project_list_item.xml @@ -0,0 +1,65 @@ + ++ + + + + + + + + ++ + + diff --git a/app/src/enterprise/res/layout/enterprise_private_activity_email_set_password.xml b/app/src/enterprise/res/layout/enterprise_private_activity_email_set_password.xml new file mode 100644 index 000000000..675887c6c --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_private_activity_email_set_password.xml @@ -0,0 +1,116 @@ + ++ + + + + + + + + ++ + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/enterprise_project_all_list_item.xml b/app/src/enterprise/res/layout/enterprise_project_all_list_item.xml new file mode 100755 index 000000000..692e3bc14 --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_project_all_list_item.xml @@ -0,0 +1,84 @@ + ++ + ++ + + ++ + + ++ + + ++ + + + + + + + + + ++ + + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/enterprise_view_user_info.xml b/app/src/enterprise/res/layout/enterprise_view_user_info.xml new file mode 100644 index 000000000..097e7de3c --- /dev/null +++ b/app/src/enterprise/res/layout/enterprise_view_user_info.xml @@ -0,0 +1,412 @@ + ++ + + + + + + + + + + + + ++ + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/fragment_enterprise_project.xml b/app/src/enterprise/res/layout/fragment_enterprise_project.xml new file mode 100644 index 000000000..340bc16de --- /dev/null +++ b/app/src/enterprise/res/layout/fragment_enterprise_project.xml @@ -0,0 +1,83 @@ + ++ + + ++ + + + + ++ + + + + ++ + + + + + + ++ + + ++ + + + + ++ + + + + ++ + + + + + ++ + + + + + + + + + ++ + + ++ + + ++ + + ++ + + + + + + + + ++ + + + ++ + + ++ + + + + + ++ + + ++ + + + + + + + + ++ + + + + + + + + + ++ + + + + + + + diff --git a/app/src/enterprise/res/layout/fragment_enterprise_project_empty.xml b/app/src/enterprise/res/layout/fragment_enterprise_project_empty.xml new file mode 100644 index 000000000..b3dc84c6e --- /dev/null +++ b/app/src/enterprise/res/layout/fragment_enterprise_project_empty.xml @@ -0,0 +1,59 @@ + ++ + + ++ + + ++ + ++ + + + + + + + + ++ + + ++ + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/init_fragment_project_create.xml b/app/src/enterprise/res/layout/init_fragment_project_create.xml new file mode 100644 index 000000000..f8f49470b --- /dev/null +++ b/app/src/enterprise/res/layout/init_fragment_project_create.xml @@ -0,0 +1,109 @@ + ++ + + + ++ + + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/init_fragment_project_set.xml b/app/src/enterprise/res/layout/init_fragment_project_set.xml new file mode 100644 index 000000000..b5a470577 --- /dev/null +++ b/app/src/enterprise/res/layout/init_fragment_project_set.xml @@ -0,0 +1,143 @@ + ++ + + ++ + + ++ + + + + + + + + + + + + + + + + ++ + + + + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/layout/project_search_view.xml b/app/src/enterprise/res/layout/project_search_view.xml new file mode 100644 index 000000000..6fbffc544 --- /dev/null +++ b/app/src/enterprise/res/layout/project_search_view.xml @@ -0,0 +1,137 @@ + + ++ + + + ++ + + ++ + + ++ + + + + + + + + + + + + + + + + + ++ + + + + + + + + + + + + ++ + + + + + + diff --git a/app/src/enterprise/res/menu/enterprise_account_menu.xml b/app/src/enterprise/res/menu/enterprise_account_menu.xml new file mode 100644 index 000000000..60665805a --- /dev/null +++ b/app/src/enterprise/res/menu/enterprise_account_menu.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/app/src/enterprise/res/menu/enterprise_compat.xml b/app/src/enterprise/res/menu/enterprise_compat.xml new file mode 100755 index 000000000..1295a9d4f --- /dev/null +++ b/app/src/enterprise/res/menu/enterprise_compat.xml @@ -0,0 +1,14 @@ + diff --git a/app/src/enterprise/res/menu/enterprise_edit_name_menu.xml b/app/src/enterprise/res/menu/enterprise_edit_name_menu.xml new file mode 100644 index 000000000..f7a2d542c --- /dev/null +++ b/app/src/enterprise/res/menu/enterprise_edit_name_menu.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/app/src/enterprise/res/menu/enterprise_main_project.xml b/app/src/enterprise/res/menu/enterprise_main_project.xml new file mode 100644 index 000000000..afb18b1fe --- /dev/null +++ b/app/src/enterprise/res/menu/enterprise_main_project.xml @@ -0,0 +1,39 @@ + + diff --git a/app/src/enterprise/res/menu/menu_fragment_project_home.xml b/app/src/enterprise/res/menu/menu_fragment_project_home.xml new file mode 100755 index 000000000..1432887c2 --- /dev/null +++ b/app/src/enterprise/res/menu/menu_fragment_project_home.xml @@ -0,0 +1,11 @@ ++ + + + + + ++ + + + + + ++ + + + + + ++ + + + + diff --git a/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_member.png b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_member.png new file mode 100644 index 000000000..3d15a1890 Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_member.png differ diff --git a/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_project.png b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_project.png new file mode 100644 index 000000000..e4c343992 Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_account_project.png differ diff --git a/app/src/enterprise/res/mipmap-xxhdpi/enterprise_support.png b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_support.png new file mode 100644 index 000000000..7d95d3e6e Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/enterprise_support.png differ diff --git a/app/src/enterprise/res/mipmap-xxhdpi/entrance_enterprise_logo.png b/app/src/enterprise/res/mipmap-xxhdpi/entrance_enterprise_logo.png new file mode 100644 index 000000000..ce31ccd78 Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/entrance_enterprise_logo.png differ diff --git a/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_enterprise.png b/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_enterprise.png new file mode 100644 index 000000000..7c213d78f Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_enterprise.png differ diff --git a/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_order.png b/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_order.png new file mode 100644 index 000000000..9fc207909 Binary files /dev/null and b/app/src/enterprise/res/mipmap-xxhdpi/ic_setting_order.png differ diff --git a/app/src/enterprise/res/values-w820dp/dimens.xml b/app/src/enterprise/res/values-w820dp/dimens.xml new file mode 100644 index 000000000..63fc81644 --- /dev/null +++ b/app/src/enterprise/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ +- +
+ + diff --git a/app/src/enterprise/res/values/Styles.xml b/app/src/enterprise/res/values/Styles.xml new file mode 100644 index 000000000..c3c2f8f0c --- /dev/null +++ b/app/src/enterprise/res/values/Styles.xml @@ -0,0 +1,13 @@ + +64dp ++ + + \ No newline at end of file diff --git a/app/src/enterprise/res/values/colors.xml b/app/src/enterprise/res/values/colors.xml new file mode 100644 index 000000000..0e3a6533f --- /dev/null +++ b/app/src/enterprise/res/values/colors.xml @@ -0,0 +1,5 @@ + ++ diff --git a/app/src/enterprise/res/values/dimens.xml b/app/src/enterprise/res/values/dimens.xml new file mode 100644 index 000000000..47c822467 --- /dev/null +++ b/app/src/enterprise/res/values/dimens.xml @@ -0,0 +1,5 @@ +- #FF717171
+- #1E2D42
++ + diff --git a/app/src/enterprise/res/values/strings.xml b/app/src/enterprise/res/values/strings.xml new file mode 100644 index 000000000..fd5065af7 --- /dev/null +++ b/app/src/enterprise/res/values/strings.xml @@ -0,0 +1,28 @@ +16dp +16dp ++ + diff --git a/app/src/enterprise/res/values/strings_array.xml b/app/src/enterprise/res/values/strings_array.xml new file mode 100644 index 000000000..f91e4100f --- /dev/null +++ b/app/src/enterprise/res/values/strings_array.xml @@ -0,0 +1,87 @@ + +Coding 企业版 +再按一次退出Coding企业版 +企业成员 +企业账户 +项目管理 +成员管理 +售后支持 +订购状态 +选择项目 +设置企业角色 +帮助中心 +创建公告 +公告 +创建公告 + +暂时没有项目公告哦~ +输入公告内容 +删除公告 +企业设置 +企业名称 +企业头像 +个性域名 + +Coding Enterprise 是 CODING 专为企业打造的软件开发协作平台,让企业更好地管理项目成员,便捷而深入地把握开发进度,让开发流程更高效。 + ++ + diff --git a/app/src/enterprise/res/xml/bottombar_tabs.xml b/app/src/enterprise/res/xml/bottombar_tabs.xml new file mode 100644 index 000000000..79f209c9c --- /dev/null +++ b/app/src/enterprise/res/xml/bottombar_tabs.xml @@ -0,0 +1,19 @@ + ++ + +- 全部
+- 任务
+- Wiki
+- 文件
+- 代码
+- 其它
++ + +- all
+- task
+- wiki
+- file
+- code
+- other
++ + +- +
- 任务协作
+- 文件管理
+- Wiki 知识库
+- 代码托管
++ + +- +
- 任务进度与代码仓库无缝衔接
+- 云端共享,支持在线预览、编辑、评论
+- 文档书写,记录整个项目的来龙去脉
+- 提交代码、合并请求一步到位
++ + + +- 名字
+- 性别
+- 生日
+- 所在地
+- 座右铭
+- 学历
+- 学校
+- 部门
+- 工作
+- 开发技能
+- 个性标签
++ + + +- 加入时间
+- 最后活动
+- 用户名
+- 性别
+- 生日
+- 所在地
+- 座右铭
+- 学历
+- 学校
+- 部门
+- 职位
+- 开发技能
+- 个性标签
++ + + +- +
- icon-1-down.gif
+- icon-2-down.gif
+- icon-3-down.gif
+- icon-4-down.gif
++ + +- +
- icon-1-up.gif
+- icon-2-up.gif
+- icon-3-up.gif
+- icon-4-up.gif
++ \ No newline at end of file diff --git a/app/src/enterprise/res/xml/bottombar_tabs1.xml b/app/src/enterprise/res/xml/bottombar_tabs1.xml new file mode 100644 index 000000000..faacfc0a5 --- /dev/null +++ b/app/src/enterprise/res/xml/bottombar_tabs1.xml @@ -0,0 +1,23 @@ + ++ + + + + \ No newline at end of file diff --git a/app/src/enterprise/res/xml/enterprise_file_path.xml b/app/src/enterprise/res/xml/enterprise_file_path.xml new file mode 100644 index 000000000..fcb69206d --- /dev/null +++ b/app/src/enterprise/res/xml/enterprise_file_path.xml @@ -0,0 +1,19 @@ + ++ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c6840924c..aeb01ca89 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,8 +1,6 @@+ + + + + + package="net.coding.program"> \ No newline at end of file diff --git a/app/src/main/assets/bubble.html b/app/src/main/assets/bubble.html index 0c843f07c..17c719ad3 100755 --- a/app/src/main/assets/bubble.html +++ b/app/src/main/assets/bubble.html @@ -6,7 +6,6 @@ -@@ -15,22 +13,6 @@ - - - - - - - - - - - - - - - - @@ -55,8 +37,8 @@ - - + + @@ -82,113 +64,34 @@ + + + + + + + - - - + - - - - -- -- - - - - - - - - - - - - - - + android:name="com.alipay.sdk.app.H5PayActivity" + android:configChanges="orientation|keyboardHidden|navigation|screenSize" + android:exported="false" + android:screenOrientation="behind" + android:windowSoftInputMode="adjustResize|stateHidden" />- - - - -- - - - - - - - - - - - - -- - - - - - - - - -- -- - - - - - -- - - -- - - - - + android:name="com.alipay.sdk.app.H5AuthActivity" + android:configChanges="orientation|keyboardHidden|navigation" + android:exported="false" + android:screenOrientation="behind" + android:windowSoftInputMode="adjustResize|stateHidden" /> +- -- - - - - - + + + + + + ++ android:theme="@style/ActionbarSpannerTheme1" + android:windowSoftInputMode="stateAlwaysHidden|adjustResize" /> - - + android:theme="@style/ThemeProject" + android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />- -- - - - - - - -- - - - - + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> + + + - + android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />- -- - - - - - -- - - - - - -- - - - - - -- - - - - - - - + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" + android:windowSoftInputMode="stateAlwaysHidden|adjustResize" /> - + android:label="@string/empty" + android:screenOrientation="unspecified" + android:theme="@style/Theme_CodingActionBar" /> - - - - - - - - -- -- + + + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> @@ -726,6 +562,10 @@ android:name=".login.auth.AuthListActivity" android:label="@string/auth_list_activity" android:screenOrientation="portrait" /> + + android:label="@string/empty" + android:screenOrientation="portrait" + android:theme="@style/Theme_CodingActionBar" /> - - + - + android:screenOrientation="portrait" + android:theme="@style/AppThemeNoActionbar" /> + android:screenOrientation="portrait" + android:theme="@style/AppThemeNoActionbar" /> + android:screenOrientation="portrait" + android:theme="@style/AppThemeNoActionbar" /> --> - - @@ -891,6 +724,7 @@+ + + + + + + + + + + + + + + + + + 冒泡详情 + + +${webview_content} + + + + + +